Bitwise rotation (Circular shift)

前端 未结 5 1792
粉色の甜心
粉色の甜心 2021-01-05 08:04

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 “

相关标签:
5条回答
  • 2021-01-05 08:09

    C++20 provides std::rotl and std::rotr in the <bit> header. An example from cppreference.com:

    #include <bit>
    #include <bitset>
    #include <cstdint>
    #include <iostream>
    
    int main()
    {
        std::uint8_t i = 0b00011101;
        std::cout << "i          = " << std::bitset<8>(i) << '\n';
        std::cout << "rotl(i,0)  = " << std::bitset<8>(std::rotl(i,0)) << '\n';
        std::cout << "rotl(i,1)  = " << std::bitset<8>(std::rotl(i,1)) << '\n';
        std::cout << "rotl(i,4)  = " << std::bitset<8>(std::rotl(i,4)) << '\n';
        std::cout << "rotl(i,9)  = " << std::bitset<8>(std::rotl(i,9)) << '\n';
        std::cout << "rotl(i,-1) = " << std::bitset<8>(std::rotl(i,-1)) << '\n';
    }
    

    I believe std::bitset is only used in this example for its stream formatting.

    0 讨论(0)
  • 2021-01-05 08:09

    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.

    0 讨论(0)
  • 2021-01-05 08:23

    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).

    0 讨论(0)
  • 2021-01-05 08:29

    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));
    }
    
    0 讨论(0)
  • 2021-01-05 08:35

    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 :)

    0 讨论(0)
提交回复
热议问题