位运算

48 阅读4分钟

在计算机中所有数据都是以二进制的形式存储的,位运算直接对二进制数据进行运算操作,省略了进制间的转换。

理论上,位运算比加减运算的效率略高,比乘除运算效率高很多,不过在目前最新的java版本下,加减运算的效率能和位运算持平,而乘除运算的效率还是落后于位运算很多。

在java中,主要有以下7种位运算符:

&(与)

规则:相同位置的数值都为1,结果为1,否则结果为0。

举例:

1 & 2 = 0

= 0000 0000 0000 0000 0000 0000 0000 0001 & 0000 0000 0000 0000 0000 0000 0000 0010 

= 0000 0000 0000 0000 0000 0000 0000 0000

|(或)

规则:相同位置的数值有一个为1,结果为1,否则结果为0。

举例:

1  2 = 3

= 0000 0000 0000 0000 0000 0000 0000 0001 & 0000 0000 0000 0000 0000 0000 0000 0010 

= 0000 0000 0000 0000 0000 0000 0000 0011

^(异或)

规则:相同位置的数值不相同时,结果为1,相同时,结果为0。

举例:

1 ^ 2 = 3 

= 0000 0000 0000 0000 0000 0000 0000 0001 ^ 0000 0000 0000 0000 0000 0000 0000 0010 

= 0000 0000 0000 0000 0000 0000 0000 0011

~(非)

规则:每个位置的数值都变更为相反的数,比如1变更为0,0变更为1。

举例:

~1 = -2 

= ~ 0000 0000 0000 0000 0000 0000 0000 0001 
= 1111 1111 1111 1111 1111 1111 1111 1110(补码)
= 1111 1111 1111 1111 1111 1111 1111 1101(反码)
= 1000 0000 0000 0000 0000 0000 0000 0010(原码)

<<(左移)

规则:所有数值向左移动,高位丢弃,低位补0。

如果你的计算机是32位系统时,左移32位相当于没有移动。这是因为移动的位数其实是对32求余后的余数。

比如x << n,其实是将x向左移动n % 32位。

举例:

-1 << 2 = -4 

= 1111 1111 1111 1111 1111 1111 1111 1111 << 2 

= 1111 1111 1111 1111 1111 1111 1111 1100(补码)

= 1111 1111 1111 1111 1111 1111 1111 1011(反码) 

= 1000 0000 0000 0000 0000 0000 0000 0100(原码)
1 << 2 = 4

= 0000 0000 0000 0000 0000 0000 0000 0001 << 2 
= 0000 0000 0000 0000 0000 0000 0000 0100

>>(右移)

规则:所有数值向右移动,低位丢弃,高位补符号位。

和 << 一样,移动的位数是求余后的余数。

举例:

-1 >> 2 = -1

= 1111 1111 1111 1111 1111 1111 1111 1111 >> 2 
= 1111 1111 1111 1111 1111 1111 1111 1111(补码) 
= 1111 1111 1111 1111 1111 1111 1111 1110(反码) 
= 1000 0000 0000 0000 0000 0000 0000 0001(原码)
5 >> 2 = 1

= 0000 0000 0000 0000 0000 0000 0000 0101 >> 2 
= 0000 0000 0000 0000 0000 0000 0000 0001

>>>(无符号右移)

规则:所有数值向右移动,低位丢弃,高位补0。

和 << 一样,移动的位数是求余后的余数。

举例:

-1 >>> 2 = 1073741823

= 1111 1111 1111 1111 1111 1111 1111 1111 >>> 2 
= 0011 1111 1111 1111 1111 1111 1111 1111

1 >>> 2 = 0

= 0000 0000 0000 0000 0000 0000 0000 0001 >>> 2
= 0000 0000 0000 0000 0000 0000 0000 0000