当我在Java中阅读System.nanoTime() API时。我发现了这一行:
one应该使用t1 - t0 < 0,而不是t1 < t0,因为可能会出现数值溢出。
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime()
用于比较两个nanoTime值的
long t0 = System.nanoTime();...long t1 = System.nanoTime();
应该使用t1 - t0 < 0,而不是t1 < t0,因为可能会出现数值溢出。
我想知道为什么t1 - t0 < 0
是防止溢出的首选方法。
因为我从其他帖子上读到A < B
比A - B < 0
更可取。
Java Integer compareTo() - why use comparison vs. subtraction?
这两件事造成了矛盾。
发布于 2013-08-24 09:52:03
Nano time不是“实时”时间,它只是一个计数器,当某个未指定的事件发生时(可能计算机启动了),它会从某个未指定的数字开始递增。
它将溢出,并在某一时刻变为负值。如果您的t0
正好在它溢出之前(即非常大的正数),而您的t1
正好在它之后(非常大的负数),那么t1 < t0
(即您的条件是错误的,因为t1
发生在t0
之后).....
但是,如果你说t1 - t0 < 0
,那么,神奇的是,出于同样的溢出(未定义)原因(非常大的负减非常大的正数将下溢),结果将是t1在t0
之后的纳秒数.....并且将会是正确的。
在这种情况下,两个错误真的就是正确的!
发布于 2013-08-24 13:59:20
当我们确定的实值差值(在溢出前)不大于包含所有可能值的集合的一半或大小时,t0 - t1 < 0
比t0 < t1
更好。
对于纳秒,它将大约是292年(纳秒以长的形式存储,long
大小的一半是2^64/2
= 2^63
纳秒~= 292年)。
因此,对于间隔小于292年的时间样本,我们应该使用t0 - t1 < 0
来获得正确的结果。
为了更好地可视化它,假设循环包含8个可能的值,它们是-4, -3, -2, -1 ,0, 1, 2, 3
。
所以时间线可以看起来像这样
real time values: .., -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, ..
overflowed values: .., 2, 3, -4, -3, -2, -1, 0, 1, 2, 3, -4, -3, -2, -1, ..
让我们看看t0 - t1 < 0
和t0 < t1
对于差值将会和不会大于4(周期大小的一半,-4是最小值,这意味着它可以是计算增量的最小结果)的表现。请注意,当t1
溢出时,只有t0 - t1 < 0
会给出正确的结果
- real values: `t0 = 3` `t1 = 4`
- overflowed: `t0 = 3` `t1 = -4`
- `t0 < t1` ==> `3 < -4` -> _**false**_
- `t0 - t1 < 0` ==> `3 - (-4) < 0` ==> `-1 < 0` (7 overflows to -1) _**true**_
因此,只有对于t0 - t1 < 0
,我们才能得到正确的结果,尽管或者可能要感谢溢出。
a)正值
- `t0 = 2`, `t1 = 3`
- `2 < 3` _**true**_
- `2 - 3 < 0` ==> `-1 < 0` _**true**_
b)负值
- `t0 = -4`, `t1 = -3`
- `-4 < -3` _**true**_
- `-4 - (-3) < 0` ==> `-1 < 0` _**true**_
对于实际增量=1的其余情况,我们还将获得t0 < t1
和t0 - t1 < 0
测试的正确结果(t0 - t1
将始终为-1
)
a1)与overflow of bigger value
- real values: `t0 = 3` `t1 = 6`
- overflowed: `t0 = 3` `t1 = -2`
- `t0 < t1` ==> `3 < -2` -> _**false**_
- `t0 - t1 < 0` ==> `3 - (-2) < 0` ==> `-3 < 0` (5 overflows to -3) _**true**_
a2) overflow的另一个案例
- real values: `t0 = 2` `t1 = 5`
- overflowed: `t0 = 2` `t1 = -3`
- `t0 < t1` ==> `2 < -3` -> _**false**_
- `t0 - t1 < 0` ==> `2 - (-3) < 0` ==> `-3 < 0` (again 5 overflows to -3) _**true**_
因此,同样只有t0 - t1 < 0
给出了正确的结果。
b)没有溢出的 t0 - t1
将始终等于-3
(-delta),因此这将始终给出正确的结果。t0 < t1
还将提供正确的重新填充
- real values: `t0 = -1` `t1 = 2`
- `t0 < t1` ==> `-1 < 2` -> _**true**_
- `t0 - t1 < 0` ==> `-1 - 2 < 0` ==> `-3 < 0` _**true**_
t0 - t1
的结果将始终等于-4
,因此它也将为<0
。使用overflow的示例
a1)
- real values: `t0 = 0` `t1 = 4`
- overflowed: `t0 = 0` `t1 = -4`
- `t0 < t1` ==> `0 < -4` -> _**false**_
- `t0 - t1 < 0` ==> `0 - (-4) < 0` ==> `-4 < 0` (4 overflows to -4) _**true**_
a2)
- real values: `t0 = 1` `t1 = 5`
- overflowed: `t0 = 1` `t1 = -3`
- `t0 < t1` ==> `1 < -4` -> _**false**_
- `t0 - t1 < 0` ==> `1 - (-3) < 0` ==> `-4 < 0` (4 overflows to -4) _**true**_
因此,同样只有t0 - t1 < 0
给出正确的结果。
没有溢出的示例显然对这两个测试都是正确的。
a1),但存在溢出
( t0的最小值为-1,因此让我们从它开始)
- real values: `t0 = -1` `t1 = 4`
- overflowed: `t0 = -1` `t1 = -4`
- `t0 < t1` ==> `-1 < -4` -> _**false**_
- `t0 - t1 < 0` ==> `-1 - (-4) < 0` ==> `3 < 0` _**false**_
a2),但存在溢出
- real values: `t0 = 1` `t1 = 6`
- overflowed: `t0 = 1` `t1 = -2`
- `t0 < t1` ==> `1 < -2` -> _**false**_
- `t0 - t1 < 0` ==> `1 - (-2) < 0` ==> `3 < 0` _**false**_ both tests failed
b1),没有溢出
- `t0 = -4`, `t1 = 1`
- `-4 < 1` _**true**_
- `-4 - 1 < 0` ==> `3 < 0` (-5 overflows to 3) _**false**_
+-------------+-----------------------------+----------------------------+
| tests if | delta <= size of half cycle | delta > size of half cycle |
| t0 is less |-----------------------------|----------------------------|
| than t1 | overflow | no overflow | overflow | no overflow |
|-------------|------------|----------------|-----------|----------------|
| t0 < t1 | - | + | - | + |
|-------------|------------|----------------|-----------|----------------|
| t0 - t1 < 0 | + | + | - | + |
|-------------|------------|----------------|-----------|----------------|
| t0 - t1 > 0 | - | - | + | - |
+-------------+------------+----------------+-----------+----------------+
发布于 2013-08-24 10:04:31
引用自API的内容实际上是:
如果连续调用的时间跨度大于大约292年(2^63纳秒),则由于数值溢出,
差异将无法准确计算已用时间。
如果t0和t1的测量间隔为292年,您将会遇到数值溢出。否则,比较或减法都可以很好地工作。
https://stackoverflow.com/questions/18414059
复制相似问题