名为“签名右移位”的运算符,将所有位向右移动指定的次数。重要的是在移位后将最左边的符号位(最高有效位MSB)填充到最左边的位。这称为符号扩展,用于在向右移动负数时保留负数的符号。>>
>>
以下是我的图表表示,其中包含一个示例,以显示其工作原理(对于一个字节):
例:
i = -5 >> 3; shift bits right three time
五合二的补码形式是1111 1011
内存表示:
MSB
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
7 6 5 4 3 2 1 0
^ This seventh, the left most bit is SIGN bit
下面是,是如何工作的?当您这样做时>>
-5 >> 3
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
| \ \
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
注意:左边最多三位是一,因为每个移位符号位都保留下来,每个位也是正确的。我已经写了符号传播,因为这三个位都是因为符号(但不是数据)。
此外,由于三个右移右移,大多数三位是损失。
右两个箭头之间的位从 中的上一位公开。-5
我认为如果我也为一个正数写一个例子会很好。下一个示例是,五是一个字节是5 >> 3
0000 0101
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
+----+----+----+---+---+---+---+---+
| \ \
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+----+----+----+---+---+---+---+---+
(______________)
The sign is
propagated
再看一遍我写的符号是传播的,所以最左边的三个零是由于符号位。
所以这就是运算符 Signed right shift 所做的,保留了左操作数的符号。>>
[你的答案]
在你的代码中,你使用运算符向右移动,所以你的权利大多数位都是松散的,结果是所有实际上在量级上的位。-15
31
>>
31
1
-1
你是否注意到,以这种方式等同于不是语句。
我相信如果一个人做i = -1>>n
,它应该被Java编译器优化为i = -1
,但这是另一回事-1 >> n
接下来,有趣的是,在Java中还有一个右移运算符可用,称为Unsign right Shift。它合乎逻辑地工作,并为每个班次操作从左填充零。因此,在每次右移时,如果您对负数和正数都使用无符号的右移位运算符,则大多数位置的左移位始终为零位。>>>
>>>
例:
i = -5 >>> 3; Unsigned shift bits right three time
下面是我的图表,演示了表达式是如何工作的?-5 >>> 3
this 3 bits are shifted
out and loss
MSB (___________)
+----+----+----+---+---+---+---+---+
| 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
+----+----+----+---+---+---+---+---+
| \ \
| ------------| ----------|
| | |
▼ ▼ ▼
+----+----+----+---+---+---+---+---+
| 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+---+---+---+---+---+
(______________)
These zeros
are inserted
你可以注意到:这次我不是在写符号位传播,而是实际上运算符插入零。因此,不保留符号,而是进行逻辑右移。>>>
>>>
据我所知,无符号右移在VDU(图形编程)中很有用,尽管我没有使用它,但在过去一些地方读过它。
我建议你读一读:>>>和>>之间的区别:算术移位右,逻辑移位右。>>
>>>
编辑:
关于无符号右移位操作员的一些有趣之处。>>>
无符号右移位运算符生成一个纯值,该值是其左操作数右移位,其右移位的扩展数为零,由其右操作数指定的位数表示。>>>
0
like and ,运算符也运算符从不引发异常。>>
<<
>>>
无符号右移位运算符的每个操作数的类型必须是整数数据类型,否则会发生编译时错误。
操作员可以对其操作数执行类型转换;与算术二元运算符不同,每个操作数都是独立转换的。如果操作数的类型是字节、短整型或字符,则在计算运算符的值之前,该操作数将转换为 int。>>>
无符号右移位运算符生成的值的类型是其左操作数的类型。LEFT_OPERAND >>> RHIGT_OPERAND
-
如果左操作数的转换类型为 int,则仅将右操作数值的五个最低有效位用作平移距离。(即 25 = 32 位 = int 中的位数)
因此,平移距离在 0 到 31 的范围内。
这里,产生的值与:r >>> s
s==0 ? r : (r >> s) & ~(-1<<(32-s))
-
如果左操作数的类型很长,则仅使用右操作数值的六个最低有效位作为平移距离。(即 25 = 64 位 = 长位数)
此处,生成的值与以下内容相同:r >>> s
s==0 ? r : (r >> s) & ~(-1<<(64-s))
一个有趣的参考:[第4章] 4.7班次运算符