JLS 15.19描述了>>>
运营商的公式。
n>>>的值s是n右移位s位 零扩展,其中:
如果n为正,则结果与n>>的结果相同。第
如果n为负数且左侧操作数的类型为int,则 结果等于表达式(n>> s)+(2<< s)的结果。
如果n为负且左侧操作数的类型为long,则 结果等于表达式(n>&gt; s)+(2L <&lt; ~s)的结果。
为什么n >>> s = (n >> s) + (2 << ~s)
,~s = 31 - s
int
和~s = 63 - s
的长度为何?
答案 0 :(得分:2)
如果n
为负,则表示符号位已设置。
>>> s
表示将s
位置向右移动,将零引入空出的位置。
>> s
表示将s
位置向右移动,将符号位的副本引入空出的位置。
E.g。
10111110000011111000001111100000 >>> 3 == 00010111110000011111000001111100
10111110000011111000001111100000 >> 3 == 11110111110000011111000001111100
显然,如果n
不是否定的,则n >> s
和n >>> s
是相同的。如果n
为否定,则差异将包含左侧的s
个,后跟全部为零。
换句话说:
(n >>> s) + X == n >> s (*)
其中X
由s
个组成,后跟32 - s
个零。
由于32 - s
中有X
个零,X
中最右边的一个出现在1 << (32 - s)
中的一个位置,等于{{ 1}},与2 << (31 - s)
相同(因为2 << ~s
和移位金额为~s == -1 - s
s的模32工作。
现在将int
添加到2 << ~s
时会发生什么?你得零!让我们在X
的案例中证明这一点。请注意,随身携带从左侧消失。
s == 7
遵循 11111110000000000000000000000000
+ 00000010000000000000000000000000
________________________________
00000000000000000000000000000000
。因此,-X == 2 << ~s
向-X
的两边添加(*)
n >>> s == (n >> s) + (2 << ~s)
对于long
,它完全相同,只是移位量是以64为模进行的,因为long
有64位。
答案 1 :(得分:2)
如果你不熟悉他所假设的基础知识,这里有一些额外的背景可以帮助你理解pbabcdefp的答案:
要理解按位运算符,您必须将数字视为二进制数字的字符串,例如。 20 = 00010100
和-4 = 11111100
(为了清晰起见而不必编写如此多的数字,我将把所有二进制数写为byte
s; int
s是相同的但是四倍的时间)。如果您不熟悉二进制和二进制操作,you can read more here。注意第一个数字是如何特殊的:它使得数字为负数,就好像它有一个可能最负数的位值(记住基本数学,数/数百位?),所以Byte.MIN_VALUE = -128 = 1000000
和设置任何其他位为1总是增加数字。要轻松读取11110011
等负数,请知道-1 = 11111111
,然后将0读取为正数为1,那么该数字与-1的距离为-1。所以11110011 = -1 - 00001100 = -1 - 12 = -13
。
同时理解~s
是按位NOT:它取所有数字并翻转它们,这实际上相当于~s = -1 - s
。例如~5 (00000101)
是-6 (11111010)
。观察我建议的读取负二进制数的方法只是一个技巧,能够读取数字的按位NOT而不是数字本身,这对于接近零的负数更容易,因为这些数字较少0
比1
s。