一、简介
程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算就是直接对整数在内存中的二进制位进行操作。比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算。举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理)。
二、运算规则
1、运算符
名称 | 符号 | 实例 | 规律 |
---|---|---|---|
按位与 | a & b | 00101&11100(5&28) -> 00100(4) | 相同位的两个数字都为1,则为1;若有一个不为1,则为0 |
按位或 | a | b | 00101|11100(5|28) -> 11101(29) | 相同位只要一个为1即为1 |
按位异或 | a ^ b | 00101^11100(5^28) -> 11001(25) | 相同位不同则为1,相同则为0 |
按位取反 | ~a | ~00101->11010(-6) | |
左移 | a << b | 6<<2(00000110左移2位)->00011000(24) | 右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2的n次方 |
带符号右移 | a >> b | 6>>2(00000110右移2位)->00000001(1) | 右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统 |
无符号右移 | a>>> b | 6>>>2->1和-6>>>2->1073741822 |
其中,-6用二进制是6的二进制取反再加1表示11111111111111111111111111111010,右移两位,就变成00111111111111111111111111111110,在用十进制表示就是1073741822。注:这里以32位整数来计算的,如果是64位,其运算结果是不一样(此处理解不是很透彻)。
二进制位数多少是根据处理器的位宽定义的,不同的处理器能处理的位数多少不一样。
2、复合运算符
运算符号 | 实例 | 相当于 |
---|---|---|
&= | a &= b | a = a&b |
|= | a |= b | a = a|b |
>>= | a >>= b | a = a>>b |
<<= | a <<= b | a = a<<b |
^= | a ^= b | a = a^b |
三、应用
1、奇数还是偶数
boolean isEvenNumber(int x) {
return (x & 1) == 0;//偶数
}
boolean isOddNumber(int x) {
return (x & 1) == 1;//奇数
}
2、整数的平均值
int average(int x, int y) {
return (x&y)+((x^y)>>1);//返回X,Y 的平均值
}
3、交换两个整数
void swap(int x , int y) {
x ^= y;
y ^= x;
x ^= y;
}
4、计算绝对值
int abs( int x ) {
int y ;
y = x >> 31 ;
return (x^y)-y ;
}
5、位运算实现加法
// 递归写法
int add(int x, int y){
if(y == 0)
return x;
int sum = x ^ y;
int carry = (x & y) << 1;
return add(sum, carry);
}
// 迭代写法
int add(int x, int y){
int sum = x ^ y;
int carry = (x & y) << 1;
while(carry != 0){
int a = sum;
int b = carry;
sum = a ^ b;
carry = (a & b) << 1;
}
return sum;
}
6、取模
int takeSurplus(int x, int y) {
return x & (y - 1);
}
//前提:y为2的n次方
未完待补充。。。