问题
I was trying to make some code in C++ about “bitwise rotation” and I would like to make this by the left shif. I didn’t know how to code this, but I found a little code in “Wikipedia” like this.
unsigned int rotl(unsigned int value, int shift) {
return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
}
Then I tried to make it work, but this code don’t give the output that I expected. Ex. I have the number unsigned int 12, in binary 1100, and when I want to do bitwise rotation by the left shif with the code above, the output is and unsigned int 24,( 11000), and it had to give the output unsigned int 9, because if I make the bitwise rotation(left shif), the first MSB bit have to be now the first bit, and all the others bits have to move one bit to left.
Can you help to understand what is the problem of that ?, or if I am doing something wrong.
Thank you.
回答1:
Following code works great
#include <cstdint>
std::uint32_t rotl(std::uint32_t v, std::int32_t shift) {
std::int32_t s = shift>=0? shift%32 : -((-shift)%32);
return (v<<s) | (v>>(32-s));
}
std::uint32_t rotr(std::uint32_t v, std::int32_t shift) {
std::int32_t s = shift>=0? shift%32 : -((-shift)%32);
return (v>>s) | (v<<(32-s));
}
and of course the test for it.
#include <iostream>
int main(){
using namespace std;
cout<<rotr(8,1)<<endl; // 4
cout<<rotr(8,-1)<<endl; //16
cout<<rotl(8,1)<<endl; //16
cout<<rotl(8,-1)<<endl; //4
cout<<rotr(4,60)<<endl; //64
cout<<rotr(4,61)<<endl; //32
cout<<rotl(4,3)<<endl; //32
cout<<rotl(4,4)<<endl; //64
return 0;
}
maybe I not provided the fastest implementation, but a portable and stable one for sure
Generic version
#include <cstdint>
template< class T>
inline T rotl( T v, std::int32_t shift){
std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
T s = shift>=0? shift%m: -((-shift)%m)
return (v<<s) | (v>>(m-s));
}
template< class T>
inline T rotr( T v, std::int32_t shift){
std::size_t m = sizeof(v)*std::numeric_limits<T>::digits;
T s = shift>=0? shift%m: -((-shift)%m)
return (v>>s) | (v<<(m-s));
}
Cheers :)
回答2:
It's because you're using an int which is 32 bits, so it worked as expected by wrapping the most significant bits to the front. Use a smaller data structure like an unsigned char to make this more managable.
回答3:
You have more than 4 bits in your integer, most likely 32, but could theoretically be 64 or 16. So your bits for the value 12 are 00000000000000000000000000001100. Doing a left rotation by 1 would naturally give you the value 00000000000000000000000000011000 (=24).
回答4:
if you want bitwise rotation over an arbitrary number of bits (for example 4), simply add a parameter to your function:
unsigned int rotl(unsigned int value, int shift, unsigned int width) {
return ((value << shift) & (UINT_MAX >> (sizeof(int) * CHAR_BIT - width))) | (value >> (width - shift));
}
来源:https://stackoverflow.com/questions/25799215/bitwise-rotation-circular-shift