• 翻转整数的二进制位


            一个无符号的整数,如果需要翻转其二进制位,可以采用下面的方法,以32位整数为例:

    unsigned int v; // 32-bit word to reverse bit order
    
    // swap odd and even bits
    v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1);
    
    // swap consecutive pairs
    v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2);
    
    // swap nibbles ... 
    v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
    
    // swap bytes
    v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);
    
    // swap 2-byte long pairs
    v = ( v >> 16             ) | ( v               << 16);

            第1步:对调相邻的1位(abcd efgh-> badc fehg)

    v = ((v >> 1) & 0x55555555) | ((v & 0x55555555)<< 1);

            第2步:对调相邻的2位(abcd efgh-> cdab ghef)

    v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);

            第3步:对调相邻的4位(abcd efgh-> efgh abcd)

    v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);

            第4步:对调相邻的8位(相邻的字节)

    v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8);

            第5步:对调相邻的16位(相邻的两字节)

    v = ( v >> 16             ) | ( v               << 16);

            经过上面的步骤,一个32位整数的二进制位已经翻转了。上面的对调步骤是互不干扰的,因此顺序可以倒过来,也就是先对调相邻16位,然后是8位、4位、2位和1位。所以,有人发明了下面的算法:

    unsigned int s = sizeof(v) * CHAR_BIT; // bit size; must be power of 2 
    unsigned int mask = ~0;         
    while ((s >>= 1) > 0) 
    {
      mask ^= (mask << s);
      v = ((v >> s) & mask) | ((v << s) & ~mask);
    }

            上面代码中,每次mask计算得到的值分别是:0x0000ffff、0x00ff00ff、0x0f0f0f0f、0x33333333和0x55555555。而且,经过测试,针对上面的s和mask,((v << s) & ~mask)与((v & mask)<< s)是相同的。所以,上面的算法,就是最开始介绍的算法。

     

            这种算法的时间复杂度为O(lg(N))。比较适合N比较大的情况,redis中,针对64位的实现如下:

    unsigned long rev(unsigned long v) {
        unsigned long s = 8 * sizeof(v); // bit size; must be power of 2
        unsigned long mask = ~0;
        while ((s >>= 1) > 0) {
            mask ^= (mask << s);
            v = ((v >> s) & mask) | ((v << s) & ~mask);
        }
        return v;
    }
    

    http://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel

  • 相关阅读:
    利用正则表达式去掉html代码
    TYPE='application/xshockwaveflash'
    SQL存储过程事务和优化方法(包括查询方式语句结合)
    C#中Bitmap类实现对图像操作的一些方法
    回首往事,碩果累累,展望未來,信心滿懷。
    此方法用于确认用户输入的不是恶意信息
    js去除字符串中的空格
    SQLServer存储过程中的简单事务处理
    SQL 2000中行加入序号用法
    C#中将byte数组转换为8bit灰度图像
  • 原文地址:https://www.cnblogs.com/gqtcgq/p/7247077.html
Copyright © 2020-2023  润新知