Java位运算基础
Updated:
基本概念
Java位运算是针对于整型数据类型的二进制进行的移位操作,我们首先需要弄明白两个问题,Java有哪些数据类型是整型数据类型和各数字进制之间转换问题。Java整型数据类型有:byte、char、short、int、long。1个字节占8位,即1byte=8bit。
常见数据类型及其所占位数如下:
Java中只有有符号整数,没有无符号整数(unsigned int),计算机在存储有符号整数时,是用该整数的补码进行存储的。只有有符号的整数才有原码,反码和补码(关于原码,反码,补码的详细介绍,参考这篇博文)。需要强调的一点是:由于计算机存储的是补码,正数的原,反,补码都一样,而负数则需要进行一定转换。以8位二进制数为例,00000001~01111111表示1~127,而负数若存储成原码形式,则10000001-11111111表示-1~-127,算上00000000=0一共127+127+1=255位,少了一位,所以要当成补码来计算,则10000001~11111111表示-127~-1,特别的10000000表示-128,所以8位二进制范围就是[-128,127],一共256位。因此计算机在进行位运算时,实际上都是补码的运算。
位运算符
以8bit为例,32bit同理
位与&
4&6
0000 0100
0000 0110
0000 0100
结果:4
位或|
-4|6
1111 1100
0000 0110
1111 1110(补码)
1000 0010(原码)
结果:-2
位非~
~4
0000 0100
1111 1011(补码)
1000 0101(原码)
结果:-5
位异或^
4^6
0000 0100
0000 0110
0000 0010
结果:2
有符号右移>>
正数,高位补0,负数,高位补1,实质等同于把这个数(十进制)除以2的n(位移位数)次幂
-4>>2
1111 1100
1111 1111
结果:-1
有符号左移<<
无论正数负数低位均补0,实质等同于把这个数(十进制)乘2的n(位移位数)次幂
-4<<2
1111 1100
1111 0000
结果:-16
无符号右移>>>
无论正数负数高位均补0,所以>>>结果一定是正数
-4>>>2
1111 1100
0011 1111
结果:2^6-1=63
Note
由于数据类型所占字节是有限的,而位移的大小却可以任意大小,所以可能存在位移后超过了该数据类型的表示范围,于是有了这样的规定:
如果为int数据类型,且位移位数大于32位,则首先把位移位数对32取模,不然位移超过总位数没意义的。所以4>>32与4>>0是等价的。
如果为long类型,且位移位数大于64位,则首先把位移位数对64取模,若没超过64位则不用对位数取模。
如果为byte、char、short,则会首先将他们扩充到32位,然后的规则就按照int类型来处理。