预备知识
原码 : 符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。
反码 : 正数的反码是其本身;负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。
补码 :
在计算机中,二进制数值是以补码的形式存放, 正数补码是其本身,负数的补码为 除符号位的(反码+1)
计算机中的数值是以其
补码
的方式存储的.
java中的基础位运算符
java中提供的基础位运算符有 与(&)
,或(|)
,非(~)
,异或(^)
,左移<<
,右移(>>)
和无符号右移(>>>)
.
除了位非(~)
是一元操作符外,其它的都是二元操作符。
以下的 A,B为二进制表示的数字.
按位与
A & B : A和B对应的二进制数位都为1时,结果才为1,其他情况为0.
A = 001101 // 13
B = 100101 // 37
A & B = 000101 // 5
按位或
A | B : A和B对应的二进制数位都为0时,结果才为0,其他情况为1.
A = 001101 // 13
B = 100101 // 37
A | B = 101101 // 45
按位非
~A : 将a的二进制表示每一位进行取反操作,0变1,1变0.
相当于相反数 - 1
A = 001101 // 13
~A = 11111111111111111111111111110010 // 32位,补码表示,第一位为符号位
// 根据上诉补码转原码为
// 10000000000000000000000000001110 // -14
按位异或
A ^ B:将A和B对应的二进制位不同,结果位为1,否则为0。
A = 001101 // 13
B = 100101 // 37
A | B = 101000 // 40
左移操作
A << B:将A的二进制表示的每一位向左移B位,左边超出的位截掉,右边不足的位补0。
在取值范围内,移动一位相当于乘2.
A = 001101 // 13
A << 1 = 011010 // 26
右移操作
A >> B: 是带符号右移,若左操作数是正数,则高位补“0”,若左操作数是负数,则高位补“1”.
在取值范围内,移动一位相当于除2.
A = 001101 // 13
A >> 1 = 000110 // 6
无符号右移操作
A >>> B: 是无符号右移,无论左操作数是正数还是负数,在高位都补“0”
在取值范围内,正数移动一位相当于除2.
A = 11111111111111111111111111110011 // -13
A >>> 1 = 01111111111111111111111111111001 // 2147483641
位运算例子
- 根据
A ^ A = 0
的特性,完成数值交换
int a = 2;
int b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println(a); // 3
System.out.println(b); // 2
- 整型字符的
乘 2 ^ n
或者除 2 ^ n
A = 001101 // 13
A >> 1 = 000110 // 相当于 13 / 2
- 判断一个数的奇偶性
最后二进制最后一位是1为奇数,为0是偶数.
boolean isOddNumber(int n){
return (n & 1) == 1;
}
A ^ -1
相当~A
.求相反数
int oppositeNumber(int num) {
return ~num + 1;
}
- 求绝对值
/**
* n>>31 取决于n的符号,若n为正数,n>>31等于0,若n为负数,n>>31等于-1
* 负数时,相当于 (n ^ -1) + 1
*/
int abs(int n) {
return (n ^ (n >> 31)) - (n >> 31);
}
- 求最大值
/**
* b & -1 == b
* ~0 == -1
*/
int max(int a, int b) {
return b & ((a - b) >> 31) | a & (~(a - b) >> 31);
}
- 求最小值
/**
* b & -1 == b
* ~0 == -1
*/
int max(int a, int b) {
return a & ((a - b) >> 31) | b & (~(a - b) >> 31);
}
- 判断符号相同
/**
* 有 0 时,方法不成立.
* @return true 表示 x和y有相同的符号, false表示x,y有相反的符号。
*/
boolean isSameSign(int x, int y) {
return (x ^ y) >= 0;
}
- 取平均值
int average(int x, int y) {
return (x + y) >> 1;
}