如何理解x&(-x), x&(x-1) ?

算法题里面,涉及到按位运算,有2个经典位运算:

  1. x&(-x) : 保留二进制下最后出现1的位置的数字,其余位置置0;
  2. x&(x-1) : 清除二进制下最后出现1的位置的数字,其余位置保持不变;

x可以将二进制数写作(A) 1 (B)的形式,其中A表示一系列01串,1表示从右向左出现的第一个数字1,B表示空串(x是奇数)或者全0串(x是偶数)。那么,
x是奇数时,x = (A) 1
x是偶数时,x = (A) 1 (0..0)

对于x&(-x)

推演

1)先求-x,
-x代表x的相反数,在计算机中存储的是补码,也就是说,-x实际存储的是x反码 + 1
x是奇数时,-x = (~A) 0 + 1 = (~A) 1
x是偶数时,-x = (~A) 0 (1..1) + 1 = (~A) 1 (0..0)

2)再求x&(-x),
x是奇数时,x&(-x) = (0..0) 1
x是偶数时,x&(-x) = (0..0) 1 (0..0)
其中,1右边的0位数保持不变。也就是说x&(-x) 会保留二进制最右边出现的1位置对于数字,其余位置置0。

应用

求非负整数x能被2的n次幂整除的n最大值。
考虑:
如果x为奇数,∵x无法被2整除,只能被1整除 ∴n=0
如果x为偶数,∵整除一个2的n次幂数,相当于右移n位
∴要求n的最大值,等价于求x最多能右移位数保持位1个数不变的移动数量 <=> 求x最右边连续0的个数

如8 = 1000b,右移3位1个数不变,右移4位1的个数减少,而8最大能被2^3整除。
24 = 1 1000b,右移3位1个数不变,右移4位1个数减少,而24最大能被2^3整除。
故只需要保留最右边的1即可,因为只需要计算最右边连续0的个数。

#include <stdio.h>

int maxPowerOfTwo(int d) {
      d = d&(-d);
      int num = 0;

      while(d) {
            num ++;
            d = d >> 1;
      }

      return num-1;
}

int main(void) {
      int n = maxPowerOfTwo(24);
      printf("%d\n", n);
      return 0;
}

对于x&(x-1)

推演

1)先求x-1,
x是奇数时,x-1 = (A) 0
x是偶数时,x-1 = (A) 0 (1..1)

2)再求x&(x-1)
x是奇数时,x&(x-1) = (A) 0
x是偶数时,x&(x-1) = (A) 0 (0..0)
其中,原来1(现在的0)右边的位数保持不变。

应用

示例1:求32位整型数d对应二进制数包含的1的个数。

#include <stdio.h>

// 求二进制数d包含1的位数
int countBitOne(int d) {
      int num = 0;
      while(d)
      {
            num++;
            d = d & (d-1);
      }

      return num;
}

int main(void) {
      int d = 0b101000;
      int nums = countBitOne(d);
      printf("%d\n", nums);
      return 0;
}

示例2:判断一个数是否为2的n次方。
思路:
2的n次方是形如1,2,4,8,16,32,...这样的数
1 -- 1b
2 -- 10b
4 -- 100b
8 -- 1000b
16 - 10000b
32 - 100000b
...
这样数的特点是二进制数据只包含1个位1,如果能将唯一的1清除,则必为0。考虑使用x&(x-1)将二进制数最后一位1清除。

#include <stdio.h>
#include <stdint.h>

bool isTwoPower(int d) {
      if (d&(d-1) == 0) {
            return true;
      }
      return false;
}

推论

  1. x - x&(-x) = x&(x-1)
    左边式子表示在二进制数x基础上,清除最右边为1的数,与右边式子含义一样。

REF

https://www.cnblogs.com/yzxag/p/12668034.html

原文链接: https://www.cnblogs.com/fortunely/p/14119264.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    如何理解x&(-x), x&(x-1) ?

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/403148

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月21日 上午11:23
下一篇 2023年4月21日 上午11:23

相关推荐