Answers:
>>
是算术右移, >>>
是逻辑右移。
在算术移位中,将扩展符号位以保留数字的符号性。
例如:用8位表示的-2将是11111110
(因为最高有效位的权重为负)。使用算术移位将其右移一位,您将得到11111111
-1。但是,逻辑上的右移并不关心该值是否可能表示带符号的数字;它只是将所有内容移至右侧,并从左侧填充0。使用逻辑移位将-2右移一位将得到01111111
。
2^k
,但我发现这是每个人的答案,这很奇怪。一串位不是数字,并且>>
始终可以在任何位串上使用:不管位串在其中扮演什么角色,以及是否具有“符号”的概念,它始终会执行相同的操作。可以通过讨论您的操作数不被解释为带正负号的情况来扩展已经很好的答案吗?我的投诉有意义吗?
String
也可以将a视为a char[]
。他不是说a char
不是数字;他只是说这是一个无符号数字。我认为那是他迷路的地方。
>>>
无符号移位;它将插入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。
>>>
是未签名的,但是为什么7>>32=7
呢?我运行了一个循环,一次执行一次换班,然后看到32
换班后又回到了7
。唯一有意义的方法是,对于每个移出的数字,它都会进入一个“外圈”。之后32
的变化,它在某种程度上达到了回到它的位置,但显然仍没有意义。到底是怎么回事?
逻辑右移(v >>> n
)返回一个值,其中in的位v
已向右移了n
位的位置,而0从左侧移入了。考虑以二进制形式移位8位值:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
如果我们将这些位解释为无符号非负整数,则逻辑右移具有将数字除以2的相应幂的作用。但是,如果数字以二进制补码表示,则逻辑右移不能正确地划分负数。例如,当这些位被解释为无符号数字时,第二个右移将移位128到32。但是,如Java中常见的那样,当位以二进制补码解释时,它将-128更改为32。
因此,如果要移位以除以2的幂,则需要算术右移(v >> n
)。它返回一个值,其中in中的位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
右移逻辑运算符(>>> N
)将比特向右移动N个位置,丢弃符号位,并用0填充N个最左边的位。例如:
-1 (in 32-bit): 11111111111111111111111111111111
之后的>>> 1
操作变为:
2147483647: 01111111111111111111111111111111
右移算术运算符(>> N
)还将位向右移N个位置,但保留符号位并将N个最左边的位填充1。例如:
-2 (in 32-bit): 11111111111111111111111111111110
之后的>> 1
操作变为:
-1: 11111111111111111111111111111111