lowbit运算是树状数组中常用的一种运算,它的直观含义就是得到从二进制的第一位开始的第一个1的位置
基本运算形式为
1.x&(~x+1)
2.x & -x
由于之前的三码也是懵懵懂懂的,导致这里理解这两种等价的lowbit运算时出现了问题
这里我通过一个样例呈现慢慢地明白了其中的原理以及三码中被我所忽略的要点
以10为例:
我们可以知道10的二进制为1010,
1. 那么由第一种运算的话先要得到~x+1的值
这里的取反是对10的二进制取反,故取反后得到0101, 再加上1,最后得到~x+1的二进制为0110
那么进行位运算后得到的结果就是(1010)&(0110)= 0010,这里可以得到1在第二位
2.由第二种运算,先要得到-x的值,那么这里需要明白的是负数在计算机的二进制存储,并非正数二进制最高位为1表示负数,而是以负数的补码形式存储
如-10得到的就是11010,我们取反后得到反码10101,再加1得到补码10110,这就是-10在计算机的存储形式
因此x&-x = (01010)&(10110) = (00010) 这里得到1在第二位。
那么这里就有个之前学习时被忽略的点是计算机存储数时全部按照一个数的补码存储的,
于是这里我们也可以得到,
正数的反码和补码与原码相同
负数的反码等于符号位不变(即最高位代表该数为负数的1不变),其余位上的数全部取反
负数的补码等于反码+1
这就是计算机中数字的存储方式
下面是测试的代码:
#include<iostream>
using namespace std;
int lowbit(int x){
return x & -x;
}
int main()
{
int a = 10, b = -10;
cout << "10的二进制表示: ";
for(int i = 4; i >= 0; i--)
cout << (a >> i & 1);
cout << endl << endl;
cout << "-10的二进制表示: ";
for(int i = 4; i >= 0; i--)
cout << (b >> i & 1);
cout << endl << endl;
cout << "10的lowbit值: " << lowbit(a) << endl;
return 0;
}