数字的为反转 (Reversing bit sequences)

参考:

 

与得到1的个数相似,大概也是这样几种方法:

  1. 一般方法:
    int reserveBit1(int i)
    {
        final int n = 31;
        int r = i;
        for (i>>>=1; i!=0; i>>>=1)
        {
             r <<= 1;
             r |= i&1;
             n--;
         }
         return r<<=n;
    }

    可以看出这个算法的主要用意就是通过遍历每个位,然后推动最某位的位不断右移,然后直到为只有了0,然后对剩下的位全部右移。这样就得到了一个反转的数。

  2. 查表法:
    int reserveBit2(int i)
    {
        int[] bitReverseTable256= new int[256]{...};
        return (bitReverseTable256[v & 0xff] << 24) | 
        (bitReverseTable256[(v >>> 8) & 0xff] << 16) | 
        (bitReverseTable256[(v >>> 16) & 0xff] << 8) |
        (bitReverseTable256[(v >>> 24) & 0xff]);
    }

    其中bitReverseTable256对应的就是每个数的反值,这样做的操作应该是很快,但是的确以空间为代价换取的,如果是c等可以直接操作内存的语言,会相对更快。

  3. 分治法及其上的更多数学分析法:

    int reserveBit3(int i)
    {
        i = (((i & 0xaaaaaaaa) >>> 1) | ((i & 0x55555555) << 1));
        i = (((i & 0xcccccccc) >>> 2) | ((i & 0x33333333) << 2));
        i = (((i & 0xf0f0f0f0) >>> 4) | ((i & 0x0f0f0f0f) << 4));
        i = (((i & 0xff00ff00) >>> 8) | ((i & 0x00ff00ff) << 8));
        return((i >>> 16) | (i << 16));
    }

    分治法的基本思想仍然是通过相邻位置的互换,然后不断扩大这种相邻范围,从而得到了最终的互换。
    而java中Integer中的实现是这样的:

    int reverseBit4(int i) 
    { i
    = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555; i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333; i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f; i = (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24); return i; }

    java中的实现操作步骤上是一样的,不一样的地方有两处,通过对操作的顺序修改减少了常量,因为前三个行的常量在同行里是一样了。然后就是将第4,5行的合并,应该是一定程度上有优化。

  4. 其他:
    另外其他算法针对一个字节的实现算法,最后要通过对每个字节的操作,实现最后的结果。
    32位数的字节反转函数:
    int reverseByteBy32(byte b)
    {
        return ((b * 0x0802 & 0x22110) | (b * 0x8020 & 0x88440)) * 0x10101 >> 16;
    }

    如果是针对long型的64位数的byte反转就是:

    int reverseByteBy64(byte b)
    {
        return (b * 0x0202020202L & 0x010884422010L) % 1023L;
    }

    如果是计算一个32位数就应该是:

    int reserveBit5(int i)
    {
        byte b0 = reserveByteBy32((byte)i);
        byte b1 = reserveByteBy32((byte)(i>>>8&0xFF));
        byte b2 = reserveByteBy32((byte)(i>>>16&0xFF));
        byte b3 = reserveByteBy32((byte)(i>>>24&0xFF));
        return (b0<<24) |(b1<<16)|(b2<<8)|b3
    }

    64位的计算类似。我觉得这样方法并不快速,因为里面操作里有一个*乘或%取模操作。

posted @ 2012-07-09 16:13  xfei6868  阅读(393)  评论(0编辑  收藏  举报