lowbit的原理和应用

众所周知,lowbit是为了获取一个数的二进制中最低位的1对应的值,比如lowbit(10) = 10,因为10的二进制表达是1010。
lowbit的实现
lowbit有两种实现方式:

  1. x & (x ^ (x - 1))
    以二进制数x = 11110000为例,x - 1=11101111,容易发现,其实就是将x的最后一个1变为0,再将后面的0都变成1,这样以来,再与x做异或:
    11110000 ^
    11101111
    结果是00011111。也就是把原数x最后一个1以及后面的 0都变成1,把最后一个1前面的1都变成0。既然前面都是零了,那么只要和原数x做和的操作,即可将异或的结果最后一个1后面的1都变成0,也就是
    11110000 &
    00011111
    得到00010000,这样就优雅得得到了最后一个1表示的数,也就是原数x的最大的可以整除的数。这里x的十进制是240,lowbit的结果是16=2^4。
  2. x & -x
    这种算法其实是利用了计算机的补码性质。计算机为了表示负数,将对应的正数二进制全部取反再加一。
    以x=11010000为例,-x=00101111 + 1 = 00110000,可以看到,取反加一后原数最后一个1后面的所有0还是0(由于加法的进位操作),原数最后一个1前的所有1都变成了0,而所有0都变成了1,其实主要核心就是将最后一个1前面的数都翻转,这样再与原数进行或操作,最后一个1前面都会是0,也就是
    11010000 &
    00110000
    结果是00010000。
lowbit的应用
  1. 统计二进制下1的个数
    先用原数计算出lowbit(x),然后用原数减去这个数,再不断lowbit。
int ans = 0; while(x > 0) { x -= x & -x; ans++; }

这也是树状数组的实现原理。
基于这个操作我们可以将分解出一个整数可以由哪些的2的幂相加构成。比如11110000也就是240=2^4+2^5+2^6+2^7。
【lowbit的原理和应用】参考:
  1. https://www.jianshu.com/p/6c3...
  2. https://blog.csdn.net/qq_4172...
  3. https://www.cnblogs.com/fusiw...

    推荐阅读