让我从您的问题结尾开始回答。如果值大于2^63-1,那么该值将会溢出。数字溢出的常见实现方式是存储结果中最不重要的可表示位;该值将会 "wrap"(请参考我在溢出方面的帖子底部)。
序列如下:
2^63-2、2^63-1、-2^63、-(2^63-1)......
现在回顾一下 Javadoc,我同意使用比较的解释很令人困惑,并且自然而然地我们会尝试比较
t1>t0
以验证是否
t1
发生在
t0
之后。你有一部分是对的。虽然我认为这不是笔误,但解释不正确。我认为它应该这样说:
对于两个值
t0
和
t1
(其中t1是在t0之后捕获的),您不应使用
t1<t0
(来检查false),而应该使用
t1-t0<0
,类似地,您不应使用
t1>t0
(来检查true),而应该使用
t1-t0>0
。
或者正式表述为:
对于两个“纳秒”值
t0
和
t1
,其中
t1
在
t0
之后被捕获,如果
t1
和
t0
的间隔<= 2^63 ns,则以下内容适用:
(t1-t0>0)==true
。
为什么?因为即使
t1
溢出(所以它是负数),结果
t1-t0
也将是负数,但它将小于-2^64,并且会“溢出回来”变成正值。
只要满足关于
t0
和
t1
之间距离的条件,上述内容就适用!如果距离大于2^64,例如:对于
t0=1;t1=-(2^64-2)
,减法结果将是:
t1-t0=-(2^64-1)
,因此指定的条件(
t1-t0>0
)将给出不正确的结果。
明白吗?)
关于溢出:
为了说明问题,假设一种使用8位存储的类型(而不是long使用的64位),因此二进制转十进制表示为:
0000 0000 => 0
0000 0001 => 1 (2^0)
0000 0010 => 2 (2^1 + 2^0)
...
1111 1111 => 255 (2^7 + 2^6 + ... + 2^1)
现在下一个数字自然是当你增加1时产生的。
将二进制1111 1111加1,将产生1 0000 0000。
(1) 0000 0000 => -256 !!!
通常,第8位上的溢出位表示(负权重)符号位。
first following value is adding 1 to most-right position
(1) 0000 0001 => -256 + 2^0 = -255
(1) 0000 0010 => -256 + 2^1 = -254
(1) 0000 0011 => -256 + 2^1 + 2^1 = -253
...
你明白了
这个问题的根源在于底层硬件注册表实现依赖于二进制值。你可以在这里阅读更详细的解释:http://www.allaboutcircuits.com/textbook/digital/chpt-2/binary-overflow/
Integer.MAX_VALUE + 1 = Integer.MIN_VALUE
。 - SomeJavaGuyt1-t0<0
也不再适用 ;) - ParkerHalo