1. 按位与(&)
位运算实质是将参与运算的数字转换为二进制,而后逐位对应进行运算。
按位与运算为:两位全为1,结果为1,即1&1=1,1&0=0,0&1=0,0&0=0。
例如51 & 5 -> 00110011 & 00000101 = 00000001 -> 51 & 5 = 1
特殊用法:
(1)与0相与可清零。
( 2 )与1相与可保留原值,可从一个数中取某些位。
例如需要取10101110中的低四位10101110 & 00001111 =00001110 ,即得到所需结果。
(3)n & 1==0 –>n为偶数,
n & 1==1 –>n为奇数;
如果n为偶数,其二进制最右边的值必定为0,和1做‘与’运算,结果必定是0
(4) n&(n-1)==0 –>检查n是否为2 的整数次幂,或者检查n是否为0
2. 按位或(|)
两位只要有一位为1,结果则为1,即1|1=1,1|0=1,0|1=1,0|0=0。
特殊用法:
(1)与0相或可保留原值。
(2)与1相或可将对应位置1。例如,将X=10100000的低四位置1,使X | 00001111 = 10101111即可。
3. 异或运算(^)
两位为“异”,即一位为1一位为0,则结果为1,否则为0。即1^1=0,1^0=1,0^1=1,0^0=0。
特殊用法:
(1)使指定位翻转:找一个数,对应X要翻转的各位为1,其余为0,使其与X进行异或运算即可。例如,X=10101110,使低四位翻转(低四位取反),X ^ 00001111 = 10100001。
(2)与0相异或保留原值。例如X ^ 00000000 = 10101110。
(3)交换两变量的值。(比借助容器法、加减法效率高)原理:一个数对同一个数连续两次进行异或运算,结果与这个数相等。
因此,交换方法为:A = A ^ B,B = A ^ B,A = A ^ B。
(4)判断两个数不同的位数。
4. 取反(~)
将一个数按位取反,即~ 0 = 1,~ 1 = 0。
只要记住求 “~” 的时候,先给原数字加1,然后取反方向就行了。
比如~5,5+1=6,取反方向,就是-6。
再比如 ~(-4),-4+1=-3,反方向,就是3。
5. 左移(<<)
将一个数左移x位,即左边丢弃x位,右边用0补x位。例:11100111 << 2 = 10011100。
拓展:
==原码==:一个整数按照绝对值大小转换为二进制即为原码;
==反码==:将二进制数按位取反,得到的即为反码;
==补码==:反码加1即为补码。
==由于计算机底层硬件的限制,负数均使用补码表示。==
若左移时舍弃的高位全为0,则每左移1位,相当于该数十进制时乘一次2。
例:11(1011) << 2 = 44(11表示为1011时实际上不完整,若计算机中规定整型的大小为32bit,则11的完整二进制形式为00000000 00000000 0000000 00001011)
求int 最大值 : (1 << 31) – 1 或者干脆 0x7FFFFFFF
6. 右移(>>)
将一个数右移若干位,右边舍弃,正数左边补0,负数左边补1。每右移一位,相当于除以一次2。
(1) 例:4 >> 2 = 1,-14 >> 2 = -4。
-14:(用八位二进制表示)
源码 1000 1110
反码 1111 0001
补码 1111 0010
1111 0010>>2 =1111 1100(负数向右移位,’10’移除被舍弃,剩余原来的最右边两位’00’,空缺的两个高位用1填补)
补码第一位表示的是正负(1:负,0:正)1111 1100(二进制),将此补码减去1,然后取反得到-14右移两位后的源码(左侧第一位为符号位,不参与取反操作):1000 0100(二进制)==-4(十进制)
注意:计算机内是以补码进行运算的,需要转换为源码是需要的数据,不能用源码进行进制转换
(2)
var a=-4>>2;
Window.alert(a); //结果是-1
原理:
-4 原码:10000000 00000100 -> 反码:11111111 11111011 -> 补码 (+1):11111111 11111100
向右移动2位 11 11111111 111111 -> (减1) 反码 11111111 11111110-> (符号位不变,其他全部取反)原码 10000000 00000001 —运行结果是-1
7. 无符号右移(>>>)
将一个数右移若干位(忽略符号),左边补0,右边舍弃。
例:-14 >>> 2 = (11111111 11111111 11111111 111100==10==) >>> 2 = (==00==111111 11111111 11111111 11111100) = 1073741820
二、Java内置的进制转换
对于原码, 反码, 补码而言, 需要注意以下几点:
(1).Java中没有无符号数, 换言之, Java中的数都是有符号的;
(2).二进制的最高位是符号位, 0表示正数, 1表示负数;
(3).正数的原码, 反码, 补码都一样;
(4).负数的反码=它的原码符号位不变, 其他位取反;
(5).负数的补码=它的反码+1;
(6).0的反码, 补码都是0;
(7).在计算机运算的时候, 都是以补码的方式来运算的.