在Java中,>>>
和>>
运算符有什么区别?
>>
是算术右移,>>>
是逻辑右移。
算术右移会将符号位扩展以保留数字的有符号性。
例如:用8位表示的-2是 11111110
(因为最高位具有负权值)。使用算术右移将其向右移动一个位会得到11111111
或-1。 然而,逻辑右移并不关心该值可能代表的是带符号的数字;它只是将所有内容向右移动,然后从左边填充0。 使用逻辑右移将我们的-2向右移动一个位会得到01111111
。
2^k
,但我觉得奇怪的是这是每个人的答案。一串比特不是一个数字,而且 >>
可以用在任何一串比特上:无论该比特串扮演什么角色,也无论它是否具有“符号”的概念,它始终执行相同的操作。如果将您已经很好的答案扩展到讨论操作数 不 被解释为有符号数的情况,那会怎样?我的抱怨有道理吗? - ZiggyString
也可以视为char[]
。他并没有说char
不是数字;他只是说它是无符号数字。我认为那就是他迷失的地方。 - bvdb>>>
代表无符号右移,它会插入0。>>
代表带符号右移,它会扩展符号位。
移位操作符包括左移操作符
<<
,带符号右移操作符>>
和无符号右移操作符>>>
。
n>>s
的值是n
向右移动s
位,并且使用符号扩展。
n>>>s
的值是n
向右移动s
位,并且使用零扩展。
System.out.println(Integer.toBinaryString(-1));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >> 16));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >>> 16));
// prints "1111111111111111"
为了更清晰地表达,添加正面对应项。System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"
由于它是正数,因此有符号和无符号的移位将在最左边的位上添加0。
>>>
始终将0放在最左边的位,而>>
将根据其符号将1或0放在左侧。
>>>
是无符号的,但为什么 7>>32=7
?我运行了一个循环,每次进行一次移位操作,并发现在经过 32
次移位后,它又回到了 7
。唯一有意义的解释是,对于每个移出的数字,它都进入了一个“外圆”。经过 32
次移位后,它以某种方式回到了原来的位置,但显然这仍然没有意义。到底发生了什么? - Ian Lfor (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));
)如果你的意思是为什么 >>32
返回原始值,可以参考这里。 - Salem逻辑右移 (v >>> n
) 返回一个值,其中 v
中的位已经向右移动了 n
位,并且从左侧填充了0。考虑将二进制写成8位值进行移位:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
如果我们将比特解释为无符号非负整数,逻辑右移的效果是将该数字除以相应的2的幂。然而,如果数字采用二进制补码表示,则逻辑右移不会正确地将负数除以2的幂。例如,在Java中通常采用二进制补码解释位时,上面第二次右移将128向右移动32位。但是当数字为-128时,则向右移32位。v >> n
)。它返回一个值,其中v
中的位已向右移动了n
位,并且从左侧复制v的最左位:01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
当位数以二进制补码表示时,算术右移的作用相当于除以2的某个幂。这是因为最左边的位是符号位。除以2的某个幂必须保持符号不变。
了解更多关于位运算和位移操作符的内容。
>> Signed right shift
>>> Unsigned right shift
位模式由左操作数给出,右操作数指定移动的位数。无符号右移运算符>>>
将一个零移入最左侧位置,
而>>
在移位后的最左侧位置取决于符号扩展。
简单来说,>>>
总是将一个零移入最左侧位置,而>>
根据数字的符号进行移位,即负数为1,正数为0。
例如使用负数和正数尝试一下。
int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));
System.out.println();
c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
输出:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0'))
; Integer.MAX_VALUE:
01111111111111111111111111111111;
Integer.MIN_VALUE:10000000000000000000000000000000;
-1:11111111111111111111111111111111;
0:00000000000000000000000000000000;
1:00000000000000000000000000000001
- Andy Dong右移逻辑运算符(>>> N
)将位向右移动N个位置,舍弃符号位并用0填充N个最左边的位。例如:
-1 (in 32-bit): 11111111111111111111111111111111
执行 >>> 1
操作后的结果为:
2147483647: 01111111111111111111111111111111
>> N
)将位向右移动N个位置,但保留符号位并用1填充N个左侧最高位。例如:-2 (in 32-bit): 11111111111111111111111111111110
执行 >> 1
操作后,结果如下:
-1: 11111111111111111111111111111111
>> Signed right shift
>>> Unsigned right shift
例子:
byte x, y; x=10; y=-10;
SOP("Bitwise Left Shift: x<<2 = "+(x<<2));
SOP("Bitwise Right Shift: x>>2 = "+(x>>2));
SOP("Bitwise Zero Fill Right Shift: x>>>2 = "+(x>>>2));
SOP("Bitwise Zero Fill Right Shift: y>>>2 = "+(y>>>2));
Bitwise Left Shift: x<<2 = 40
Bitwise Right Shift: x>>2 = 2
Bitwise Zero Fill Right Shift: x>>>2 = 2
Bitwise Zero Fill Right Shift: y>>>2 = 1073741821
>>(signed) 对于 8 >> 2 和 -8 >> 2 会得到不同的结果。
对 8 进行右移
8 = 1000(二进制表示)
进行 2 位右移
8 >> 2:
1000 >> 2 = 0010(相当于 2)
对 -8 进行右移
8 = 1000(二进制表示)
1 的补码 = 0111
2 的补码:
0111 + 1 = 1000
符号位为 1
在补码结果上进行 2 位右移
-8 >> 2:
1000 >> 2 = 1110(相当于 -2)
>>(unsigned) 对于 8 >>> 2,-8 >>> 2 将给出相同的结果。
8 的无符号右移
8 = 1000
8 >>> 2 = 0010
-8 的无符号右移
-8 = 1000
-8 >>> 2 = 0010