|、^、&、~的介绍
| 是按位或运算符号,&是按位与运算符,^是按位异或运算符,~是按位取反运算符.
| 指的是参加运算的两个对象,按二进制位进行”或”运算.
0|0=0 0|1=1 1|1=1 1|0=1
结论是 按二进制位进行”或”运算,都为0时的运算结果等于0,其他情况都为1.
& 指的是参加运算的两个对象,按二进制位进行”与”运算.
0&0=0 0&1=0 1&1=1 1&0=0
结论是 按二进制位进行”与”运算,都为1时的运算结果等于1,其他情况都为0.
^ 指的是参加运算的两个对象,按二进制位进行”异或”运算.
0^0=0 0^1=1 1^0=1 1^1=0
结论是 按二进制位进行”异或”运算,两个二进制数相同时的运算结果等于0,不同时结果为1.
所以设一个数为a(代表任何数),a^0=a, a^a=0,并且 a ^ b ^ b=b ^ a ^ b =a,即 ^ 异或运算的顺序不会影响结果.
~ 指的是参加运算的两个对象,按二进制位进行”取反”运算.
~0=1 ~1=0
结论是 按二进制位进行”取反”运算,0变成1,1变成0.注意这里说的是在二进制位上0变成1,1变成0,对十进制的0和1进行~取反运算,(int类型)0的二进制是32个0,取反就是32个1,有符号的情况下就等于-1(其他类型结果不变).1同理(int类型)前面都是0最后一个是1,取反前面31个1最后一个0,有符号的情况下就等于-2.
|、^、&、~的使用
题目1:
给定一个非空整数数组,除了某个元素只出现奇数次以外,其余每个元素均出现偶数次。找出那个出现了奇数次的元素。
代码:
int o=0;
for (int i : arr) {
o=o^i;
}
return o;
解析:
这里有两个条件,一个出现奇数次的元素,和其他元素均出现偶数次.所以排除所有出现偶数次的元素就能获取剩下的出现奇数次的元素,上面介绍^ 异或运算时提到相同的数异或自己时结果是0,0异或任何数结果不会变化,而且 ^ 异或运算的顺序不会影响结果.所以将数组里所有数遍历都进行异或运算,偶数次元素异或后变成0,奇数次的元素最后剩下自己.
题目2:
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
代码:
public int hammingWeight(int n) {
int m = 0;
while (n != 0) {
n = (n - 1) & n;
m++;
}
return m;
}
解析:
n-1之后去和n进行与运算,n-1之后二进制位最右侧的1会变成0,比如1111变成1110,1110变成1101,和原数字与运算后本来最右侧的1之后的二进制位的1不会变动,然后循环重复操作直到变成二进制位都变成0;
代码:
public int hammingWeight(int n) {
int num = 0;
while (n != 0) {
if ((n & (~n + 1)) != 0) {
n = n - (n & (~n + 1));
num++;
}
}
return num;
}
解析:
第二段代码n & (~n + 1)其实是查询二进制位最右侧的1,比如1110取反+1 等于0010 与运算(int类型32位二进制位原数字前面都是0,取反后变成1,与运算后还是0)后获取二进制10.后面n – (n & (~n + 1))就是去掉找到的那个二进制位最右侧的1,然后循环.