Efficient Algorithm for Bit Reversal (from MSB->LSB to LSB->MSB) in C

后端 未结 26 1373
情深已故
情深已故 2020-11-22 06:08

What is the most efficient algorithm to achieve the following:

0010 0000 => 0000 0100

The conversion is from MSB->LSB to LSB->MSB. All bits

相关标签:
26条回答
  • 2020-11-22 07:03

    Efficient can mean throughput or latency.

    For throughout, see the answer by Anders Cedronius, it’s a good one.

    For lower latency, I would recommend this code:

    uint32_t reverseBits( uint32_t x )
    {
    #if defined(__arm__) || defined(__aarch64__)
        __asm__( "rbit %0, %1" : "=r" ( x ) : "r" ( x ) );
        return x;
    #endif
        // Flip pairwise
        x = ( ( x & 0x55555555 ) << 1 ) | ( ( x & 0xAAAAAAAA ) >> 1 );
        // Flip pairs
        x = ( ( x & 0x33333333 ) << 2 ) | ( ( x & 0xCCCCCCCC ) >> 2 );
        // Flip nibbles
        x = ( ( x & 0x0F0F0F0F ) << 4 ) | ( ( x & 0xF0F0F0F0 ) >> 4 );
    
        // Flip bytes. CPUs have an instruction for that, pretty fast one.
    #ifdef _MSC_VER
        return _byteswap_ulong( x );
    #elif defined(__INTEL_COMPILER)
        return (uint32_t)_bswap( (int)x );
    #else
        // Assuming gcc or clang
        return __builtin_bswap32( x );
    #endif
    }
    

    Compilers output: https://godbolt.org/z/5ehd89

    0 讨论(0)
  • 2020-11-22 07:05

    Another loop-based solution that exits quickly when the number is low (in C++ for multiple types)

    template<class T>
    T reverse_bits(T in) {
        T bit = static_cast<T>(1) << (sizeof(T) * 8 - 1);
        T out;
    
        for (out = 0; bit && in; bit >>= 1, in >>= 1) {
            if (in & 1) {
                out |= bit;
            }
        }
        return out;
    }
    

    or in C for an unsigned int

    unsigned int reverse_bits(unsigned int in) {
        unsigned int bit = 1u << (sizeof(T) * 8 - 1);
        unsigned int out;
    
        for (out = 0; bit && in; bit >>= 1, in >>= 1) {
            if (in & 1)
                out |= bit;
        }
        return out;
    }
    
    0 讨论(0)
  • 2020-11-22 07:08

    You might want to use the standard template library. It might be slower than the above mentioned code. However, it seems to me clearer and easier to understand.

     #include<bitset>
     #include<iostream>
    
    
     template<size_t N>
     const std::bitset<N> reverse(const std::bitset<N>& ordered)
     {
          std::bitset<N> reversed;
          for(size_t i = 0, j = N - 1; i < N; ++i, --j)
               reversed[j] = ordered[i];
          return reversed;
     };
    
    
     // test the function
     int main()
     {
          unsigned long num; 
          const size_t N = sizeof(num)*8;
    
          std::cin >> num;
          std::cout << std::showbase << std::hex;
          std::cout << "ordered  = " << num << std::endl;
          std::cout << "reversed = " << reverse<N>(num).to_ulong()  << std::endl;
          std::cout << "double_reversed = " << reverse<N>(reverse<N>(num)).to_ulong() << std::endl;  
     }
    
    0 讨论(0)
  • 2020-11-22 07:08

    How about the following:

        uint reverseMSBToLSB32ui(uint input)
        {
            uint output = 0x00000000;
            uint toANDVar = 0;
            int places = 0;
    
            for (int i = 1; i < 32; i++)
            {
                places = (32 - i);
                toANDVar = (uint)(1 << places);
                output |= (uint)(input & (toANDVar)) >> places;
    
            }
    
    
            return output;
        }
    

    Small and easy (though, 32 bit only).

    0 讨论(0)
  • 2020-11-22 07:09
    unsigned char ReverseBits(unsigned char data)
    {
        unsigned char k = 0, rev = 0;
    
        unsigned char n = data;
    
        while(n)
    
        {
            k = n & (~(n - 1));
            n &= (n - 1);
            rev |= (128 / k);
        }
        return rev;
    }
    
    0 讨论(0)
  • 2020-11-22 07:10

    Presuming that you have an array of bits, how about this: 1. Starting from MSB, push bits into a stack one by one. 2. Pop bits from this stack into another array (or the same array if you want to save space), placing the first popped bit into MSB and going on to less significant bits from there.

    Stack stack = new Stack();
    Bit[] bits = new Bit[] { 0, 0, 1, 0, 0, 0, 0, 0 };
    
    for (int i = 0; i < bits.Length; i++) 
    {
        stack.push(bits[i]);
    }
    
    for (int i = 0; i < bits.Length; i++)
    {
        bits[i] = stack.pop();
    }
    
    0 讨论(0)
提交回复
热议问题