Java 位运算
位运算都是基于二进制数计算的,最高位为0代表正数,最高位为1的代表负数。
数字在计算机中的存储,是其补码。比如5存储在计算机上为0000 0101,-5存储在计算机上为 1111 1011。
运算是基于补码进行的。
已知一个数的补码,求原码的操作分两种情况: (1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。 (2)如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:符号位为1,其余各位取 反,然后再整个数加1。
正数的反码 = 补码 = 原码
负数的原码 = 即用第一位表示符号, 其余位表示值;
负数的反码=符号位为1,其它位是原码取反.
负数的补码=在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
比如: 5的原码、反码、补码都是0000 0101
-5的原码为1000 0101,
反码为1111 1010,
补码为1111 1011
与运算 & : 两个操作数中位都为1,结果才为1,否则结果为0。
下面看个例子,求一个数a能否被2的整数倍整除。
能被2^n整除(n >= 1),则a的二进制表示中,末n-1位全为0(从末n位开始到最高位都是2^n的整数倍)
- (a % 2) <==> (a & 1)
- (a % 4) <==> (a & 3)
- (a % 8) <==> (a & 7)
- (a % 16) <==> (a & 15) <==> (a & ((1 << 4) - 1))
- ……
解析: 以24为例,判断能否被8整除。24的补码为0001 1000。2的3次方为8. 即被8整除的数,其二进制码末3位为0.
位运算符 & 的运算规则为 : 相同位的两个数字都为1,则为1;若有一个不为1,则为0。
24的补码的末三位为000,能与000 & ? = 0的最大二进制数是111,即数字7。
上面左边的表达式可能会被编译器自动优化。
其他位云算符:
或运算 | : 相同位只要一个为1即为1。
存储模式,我们需要的结果是需要将补码转化为原码,换算过程:按位取反1000 0101 再整个+1,故原码为
1000 0110 = -6(最高位为负,二进制转化为十进制为6)
左移<< : 左移运算符,num << n,相当于num乘以2^n。
5<<1 结果为10, 5的原码为0000 0101,左移1位后 0000 1010。(向左平移位,末位补0)
-5<<1 结果为-10,-5的原码为1000 0101,补码为1111 1011,左移1位后1111 0110,对1111 0110求原码为 1000 1010。(符号位不变,向左平移,末尾补0)
右移>> : 右移运算符,num >> n,相当于num除以2^n
5>>1 结果为2,5的原码为0000 0101,右移1位后 0000 0010。(向右平移位,最高位补0)
-5>>1 结果为-3,-5的原码为1000 0101,补码为1111 1011,右移1位后1111 1101,对1111 1101求原码为1000 0011 。(符号位不变,向右平移,最高位补0)
无符号右移>>> : 无符号右移,忽略符号位,空位都以0补齐
5>>>1 结果为2,5的原码为0000 0101,右移1位后 0000 0010。(向右平移位,最高位补0,忽略符号位)
-5>>>1结果为2147483645,-5的原码为1000 0101,补码为1111 1011,向右无符号平移1位后 0111 1111 1111 1111 1111 1111 1111 1101,对0111 1101求原码为0111 1101。

浙公网安备 33010602011771号