首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中使用t1 ()时,为什么要使用System.nanoTime- t0 < 0,而不是t1 < t0

在Java中使用t1 ()时,为什么要使用System.nanoTime- t0 < 0,而不是t1 < t0
EN

Stack Overflow用户
提问于 2013-08-24 09:34:46
回答 4查看 1.4K关注 0票数 19

当我在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 < BA - B < 0更可取。

Java Integer compareTo() - why use comparison vs. subtraction?

这两件事造成了矛盾。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-24 09:52:03

Nano time不是“实时”时间,它只是一个计数器,当某个未指定的事件发生时(可能计算机启动了),它会从某个未指定的数字开始递增。

它将溢出,并在某一时刻变为负值。如果您的t0正好在它溢出之前(即非常大的正数),而您的t1正好在它之后(非常大的负数),那么t1 < t0 (即您的条件是错误的,因为t1发生在t0之后).....

但是,如果你说t1 - t0 < 0,那么,神奇的是,出于同样的溢出(未定义)原因(非常大的负减非常大的正数将下溢),结果将是t1在t0之后的纳秒数.....并且将会是正确的。

在这种情况下,两个错误真的就是正确的!

票数 12
EN

Stack Overflow用户

发布于 2013-08-24 13:59:20

当我们确定的实值差值(在溢出前)不大于包含所有可能值的集合的一半或大小时,t0 - t1 < 0t0 < t1更好。

对于纳秒,它将大约是292年(纳秒以长的形式存储,long大小的一半是2^64/2 = 2^63纳秒~= 292年)。

因此,对于间隔小于292年的时间样本,我们应该使用t0 - t1 < 0来获得正确的结果。

为了更好地可视化它,假设循环包含8个可能的值,它们是-4, -3, -2, -1 ,0, 1, 2, 3

所以时间线可以看起来像这样

代码语言:javascript
复制
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 < 0t0 < t1对于差值将会和不会大于4(周期大小的一半,-4是最小值,这意味着它可以是计算增量的最小结果)的表现。请注意,当t1溢出时,只有t0 - t1 < 0会给出正确的结果

  1. delta = 1 with overflow of bigger value (注意:我们没有使较小的值溢出,因为这意味着两个值处于同一周期,因此计算将与不存在任何溢出时相同)

代码语言:javascript
复制
- 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,我们才能得到正确的结果,尽管或者可能要感谢溢出。

  1. delta = 1,但这次没有溢出

a)正值

代码语言:javascript
复制
- `t0 = 2`, `t1 = 3`
- `2 < 3` _**true**_
- `2 - 3 < 0` ==> `-1 < 0` _**true**_

b)负值

代码语言:javascript
复制
- `t0 = -4`, `t1 = -3`
- `-4 < -3` _**true**_
- `-4 - (-3) < 0` ==> `-1 < 0` _**true**_

对于实际增量=1的其余情况,我们还将获得t0 < t1t0 - t1 < 0测试的正确结果(t0 - t1将始终为-1)

  1. delta = 3 (几乎是周期的一半)

a1)与overflow of bigger value

代码语言:javascript
复制
- 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的另一个案例

代码语言:javascript
复制
- 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还将提供正确的重新填充

代码语言:javascript
复制
- real values: `t0 = -1` `t1 = 2`
- `t0 < t1` ==> `-1 < 2`  -> _**true**_
- `t0 - t1 < 0` ==> `-1 - 2 < 0` ==> `-3 < 0` _**true**_

  1. delta =4 t0 - t1的结果将始终等于-4,因此它也将为<0

使用overflow示例

a1)

代码语言:javascript
复制
- 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)

代码语言:javascript
复制
- 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给出正确的结果。

没有溢出的示例显然对这两个测试都是正确的。

  1. delta = 5 (或更多)

a1),但存在溢出

( t0的最小值为-1,因此让我们从它开始)

代码语言:javascript
复制
- 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),但存在溢出

代码语言:javascript
复制
- 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),没有溢出

代码语言:javascript
复制
- `t0 = -4`, `t1 = 1`
- `-4 < 1` _**true**_
- `-4 - 1 < 0` ==> `3 < 0` (-5 overflows to 3) _**false**_

代码语言:javascript
复制
+-------------+-----------------------------+----------------------------+
|  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 |      -     |       -        |     +     |       -        |
+-------------+------------+----------------+-----------+----------------+
票数 9
EN

Stack Overflow用户

发布于 2013-08-24 10:04:31

引用自API的内容实际上是:

如果连续调用的时间跨度大于大约292年(2^63纳秒),则由于数值溢出,

差异将无法准确计算已用时间。

如果t0和t1的测量间隔为292年,您将会遇到数值溢出。否则,比较或减法都可以很好地工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18414059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档