目录html
运算符 | 用法 | 描述 |
---|---|---|
按位与( AND) | a & b |
对于每个比特位,只有两个操做数相应的比特位都是1时,结果才为1,不然为0。 |
按位或(OR) | a | b |
对于每个比特位,当两个操做数相应的比特位至少有一个1时,结果为1,不然为0。 |
按位异或(XOR) | a ^ b |
对于每个比特位,当两个操做数相应的比特位有且只有一个1时,结果为1,不然为0。 |
按位非(NOT) | ~ a |
反转操做数的比特位,即0变成1,1变成0。 |
左移(Left shift) | a << b |
将 a 的二进制形式向左移 b (< 32) 比特位,右边用0填充。 |
有符号右移 | a >> b |
将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位。 |
无符号右移 | a >>> b |
将 a 的二进制表示向右移b (< 32) 位,丢弃被移出的位,并使用 0 在左侧填充。 |
须要注意如下几点:java
> -15>>2 -4 > 15>>2 3
由于15=0000 1111(二进制),右移二位,最高位由符号位填充将获得0000 0011即3。-15 = 1111 0001(二进制),右移二位,最高位由符号位填充将获得1111 1100即-4。算法
一个数在计算机中的二进制表示形式,叫作这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号,正数为 0, 负数为 1。因此,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。.net
原码就是符号位加上真值的绝对值,即用第一位表示符号,其他位表示值。好比 8 位二进制:code
[+1] 原 = 0000 0001 [-1] 原 = 1000 0001
第一位是符号位,由于第一位是符号位,因此 8 位二进制数的取值范围就是:[1111 1111 , 0111 1111],即:[-127 , 127]htm
反码的表示方法是:正数的反码是其自己,负数的反码是在其原码的基础上,符号位不变,其他各个位取反。blog
[+1] = [00000001] 原 = [00000001] 反 [-1] = [10000001] 原 = [11111110] 反
补码的表示方法是:正数的补码就是其自己,负数的补码是在其原码的基础上,符号位不变,其他各位取反,最后 + 1。(即在反码的基础上 + 1)ip
[+1] = [00000001] 原 = [00000001] 反 = [00000001] 补 [-1] = [10000001] 原 = [11111110] 反 = [11111111] 补
由于在电脑中存储数值都是用补码来进行存储的,因此对负数的计算首先要先算出它的补码值内存
value << num
num 指定要移位值;value 移动的位数。get
将左操做数(value)转为二进制数后向左边移动 num 位,而且在低位补 0,高位丢弃。
例如:5 << 2
0000 0000 0000 0000 0000 0000 0000 0101 5 的补码(同原码) 0000 0000 0000 0000 0000 0000 0001 0100 左移 2 位后,低位补 0。换算成 10 进制为 20
若是移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模。如:对 int 类型(最大位数 32)的数值移动 33 位,实际上只移动了 33 % 32 = 1
位。
注:n 位二进制,最高位为符号位,所以表示的数值范围:−2(n−1)−2(n−1) —— 2(n−1)−12(n−1)−1,因此模为:2(n−1)2(n−1)。
在数字没有溢出的前提下,对于正数和负数,左移一位都至关于乘以 2 的 1 次方,左移 n 位就至关于乘以 2 的 n 次方。如:5 << 2
至关于 5∗22=205∗22=20。
若是移进高阶位(int 31 或 long 63 位),那么该值将变为负值。如:1 << 31 = -2147483648
value >> num
num 指定要移位值;value 移动的位数。
将左操做数(value)转为二进制数后向右边移动 num 位,符号位不变,高位补上符号位(若左操做数是正数,则高位补 0,若左操做数是负数,则高位补 1),低位丢弃。
右移时,被移走的最高位(最左边的位)由原来最高位的数字补充,这叫作符号位扩展(保留符号位)(sign extension),在进行右移操做时用来保持负数的符号。
例如:7 >> 2
0000 0000 0000 0000 0000 0000 0000 0111 7 的补码(同原码) 0000 0000 0000 0000 0000 0000 0000 0001 右移 2 位后,高位补 0。换算成 10 进制为 1
例如:-7 >> 2
1000 0000 0000 0000 0000 0000 0000 0111 -7 的原码 1111 1111 1111 1111 1111 1111 1111 1000 -7 的反码 1111 1111 1111 1111 1111 1111 1111 1001 -7 的补码 1111 1111 1111 1111 1111 1111 1111 1110 右移 2 位后,高位补 1 1000 0000 0000 0000 0000 0000 0000 0010 补码转原码。换算成 10 进制为 -2
正数右移 n 位至关于除以 2 的 n 次方而且舍弃了余数。如:7 >> 2
至关于: 7/22=17/22=1。
负数右移 n 位至关于除以 2 的 n 次方,若是有余数 -1。如:-7 >> 2
至关于: 7∗22−1=−27∗22−1=−2。
value >>> num
num 指定要移位值;value 移动的位数。
将左操做数(value)转为二进制数后向右边移动 num 位,0 补最高位(忽略了符号位扩展)。
无符号右移运算只是对 32 位和 64 位的值有意义。
例如:-7 >>> 2
1000 0000 0000 0000 0000 0000 0000 0111 -7 的原码 1111 1111 1111 1111 1111 1111 1111 1001 -7 的补码 0011 1111 1111 1111 1111 1111 1111 1110 右移 2 位后,高位补 0。换算成 10 进制为 1073741822
负数的存储以补码(符号位保持不变,其余位是存储数的绝对值按位取反加1)方式:故而-1在存储空间的存放为:
其值为2^32-1=4294967255;
11111111 11111111 11111111 11111111
故而无符号右移10位:变成以下图所示:
00000000 00111111 11111111 11111111
其值:
2^22-1=4194303 或 (1<<22)-1=4194303
11111111 11111111 11111111 11111111
若为负数,则在存储时首位表示符号位,其值为1,表示该值是负数的移位,在移位过程当中,高位补1,
而后求补码加1;
10000000 00000000 00000000 00000001
-1>>10 结果仍是-1
若符号位是0,表示是正数,在移位过程当中高位补零,二者的前提是符号位保持不变:
-1L ^ (-1L << n)
或 ~(-1L << 5)
。int i = 234; byte b = (byte) i; // 结果:b = -22 // 转换过程: // 0000 0000 0000 0000 0000 0000 1110 1010 # int 234 的补码(与原码相等) // 1110 1010 # byte 低位截取 // 1001 0110 # 求得补码,转为 10 进制为 -22 int x = b ; // 结果为:x = -22;8 位 byte 的转 32 的 int,值不变。 int y = b & 0xff; // 结果为:x = 234; 能够经过将其和 0xff 进行位与(&)获得它的无符值 // 转换过程: // 1001 0110 # byte -22 的原码 // 1000 0000 0000 0000 0000 0000 0001 0110 # int -22 的原码 // 1111 1111 1111 1111 1111 1111 1110 1010 # int -22 补码 // 0000 0000 0000 0000 0000 0000 1111 1111 # 0xff 的二进制数 // 0000 0000 0000 0000 0000 0000 1110 1010 # 和 0xff 进与操做的结果,转换为 10 进制为 234