一.位运算的奇淫技巧
1.判断奇偶性
代码演示
使用位运算,判断奇偶性
System.out.println(31&1);
System.out.println(30&1);
输出:
1 //31是奇数
0 //30是偶数
解释
与(AND)运算:当A和B全为1时,输出1,否则输出0。
& | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
(31) → (0000 0000 ....... 0001 1111)
(1) → (0000 0000 .............0001) &
= (0000 0000 .............0001) → (1) 奇数
-----------------------------------------------------------
(30) → (0000 0000 ....... 0001 1110)
(1) → (0000 0000 .............0001) &
= (0000 0000 .............0000) → (0) 偶数
2.交换两个整数变量的值
代码演示
利用位运算,直接交换两个整数变量的值
int a = 10;
int b = 8;
a = a^b;
b = a^b;
a = a^b;
System.out.println("a = "+a);
System.out.println("b = "+b);
输出:
a = 8
b = 10
解释
异或(xor)运算:两个数不相同为1,相同为0;不进位的加法,1+1=0,0+0=0,1+0=0。
^ | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
异或运算的性质
1.任何数和自己异或皆为0。
2.任何数与另一个数连续异或两次还是自己。
第一次运算:
a = (10) = 0000.............1010
b = (8) = 0000.............1000 ^
0000.............0010
将结果赋值给a后
a = 0000.............0010
b = 0000.............1000
--------------------------------------------------
第二次运算:
a = 0000.............0010
b = 0000.............1000 ^
0000.............1010
将结果赋值给b后
a = 0000.............0010
b = 0000.............1010(此时b已经得到a的值)
--------------------------------------------------
第三次运算:
a = 0000.............0010
b = 0000.............1010 ^
0000.............1000
将结果赋值给a后
a = 0000.............1000
b = 0000.............0010
交换完成
--------------------------------------------------
a = a^b;
b = a^b; 相当于初始的a连续异或b两次:a^b^b 此时得到值为a,又将他赋值给b
a = a^b; 此时b的值已经是初始a的值,a的值是初始a异或初始b的值,此时的a^b等价于初始的b连续异或两次a,结果是初始b的值,把他赋值给a,交换完成。
3.求函数绝对值
代码演示
System.out.println(8+ "的绝对值是:"+((8^(8>>31))+(8>>>31)));
System.out.println(-8+ "的绝对值是:" + ((-8^(-8>>31))+(-8>>>31)));
输出:
8的绝对值是:8
-8的绝对值是:8
补充
1.左移: <<
左移,即除符号位外,所有二进制位向高位移动指定位数,低位补0。左移一位,等价于一个数扩大2倍。
代码演示:
System.out.println(10<<2); //<<符号左边是要作出移动的数,右边是要移动几位
输出:
40
解释:
(10) = 0000........0000 1010
<<2 = 0000........0010 1000 = (40)
2.右移: >>
右移,即除符号位外,所有二进制位向低位移动指定位数,高位补符号位。右移一位,约等于一个数缩小2倍(会产生精度丢失)。
代码演示:
System.out.println(10>>2);
System.out.println(-10>>2);
输出:
2
-3
解释:
(10) = 0000........0000 1010
>>2 = 0000........0000 0010 = (2)
--------------------------------------------------
(-10) = 1111........1111 0110(补) 负数的补码
>>2 = 1111........1111 1101(补) = 1000.........0011(原) = -3
2.无符号右移: >>>
无符号右移,即向右移位时,连同符号位一起移动,最高位补0
代码演示:
System.out.println(-10>>>2);
输出:
1073741821
解释:
(-10) = 1111........1111 0110(补)
>>>2 = 0011........1111 1101(补) = 1073741821(补码直接转换为真值)
解释
整数在java中占4个字节,32位,
8>>>31和-8>>>31为了得到数字的最高位
8>>31 得到一串32位全为0的二进制数,此数与8异或,还是8,加上先前的8>>>31得到8
-8>>>31得到一串32位全为1的二进制数,此数与-8异或,相当于对-8连同符号位一起取反,然后加上-8>>>31。负数的补码等于正数连同符号位取反加一,负数求绝对值相当于此过程的逆过程。
才疏学浅,如果有写的不对的地方,请在评论区给出,谢谢!