如何理解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

posted @ 2020-12-11 11:01  明明1109  阅读(1174)  评论(0编辑  收藏  举报