如何比较两个纳米时间值?[javadoc混淆]
我已经阅读了如何比较两个纳米时间值?[javadoc混淆],java,time,comparison,integer-overflow,Java,Time,Comparison,Integer Overflow,我已经阅读了System.nanoTime()的javadoc,看起来一切都很清楚。直到最后一段: 比较两个nanoTime值的步骤 longt0=System.nanoTime() … long t1=System.nanoTime() 应该使用t1-t0t0。他们提到了数字溢出,我不太明白他们的意思。关于数字溢出,这里提到: 由于数字溢出,连续调用的差异超过大约292年(2^63纳秒)将无法正确计算经过的时间 好吧,既然纳米时间是作为一个长值存储的,它最终会在292年内溢出。接下来会发生什么
System.nanoTime()
的javadoc,看起来一切都很清楚。直到最后一段:
比较两个nanoTime值的步骤
longt0=System.nanoTime()代码>
…
long t1=System.nanoTime()代码>
应该使用t1-t0<0,而不是t1
有两件事我不清楚:
为什么要检查t1
是否在t0
之后执行t1
?我的理解是纳米时间总是在增加。所以,我宁愿选择t1>t0
让我们假设这是一个输入错误,他们的意思是正确的检查是t1-t0>0
。我仍然不明白为什么这是正确的检查方法,而不是t1>t0
。他们提到了数字溢出,我不太明白他们的意思。关于数字溢出,这里提到:
由于数字溢出,连续调用的差异超过大约292年(2^63纳秒)将无法正确计算经过的时间
好吧,既然纳米时间是作为一个长值存储的,它最终会在292年内溢出。接下来会发生什么?它是否从头开始,即最低负值-2^63?还是它总是停止测量并返回(2^63-1)?让我从你问题的末尾开始。是如果值大于2^63-1,则该值将溢出。溢出的常见实现是存储结果的最低有效表示位;值将换行(您可以在我关于溢出的帖子底部看到,以供参考)
顺序如下:2^63-2,2^63-1,-2^63,-(2^63-1)…
现在回顾Javadoc,我同意关于使用比较的解释令人困惑,我们自然会尝试比较t1>t0
,以验证t1
是否发生在t0
之后。你部分是对的。虽然我不认为这是一个打字错误,但它没有得到正确的解释。我认为应该说:
对于两个值t0
和t1
(其中t1在t0之后捕获),不应使用t1
(检查false
),而应使用t1-t0<0
,同样,不应使用t1>t0
(检查true
),而应使用t1-t0
或将其正式化:
对于两个“nano”值t0
和t1
,其中t1
在t0
之后被捕获,如下所示:(t1-t0>0)==true
只要t1
和t0
之间的周期为0,就会给出不正确的结果
对吧?:)
溢流
为了便于解释,LAT假设使用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。
将1添加到二进制1111111将产生1 0000 0000
(1)0000 0000=>-256代码>通常,位置8上的溢出位将表示(负权重)符号位
你明白了吗
其根源在于依赖于二进制值的底层硬件注册表实现。
例如,您可以在这里阅读更详细的解释:好吧,javadoc
说明了真相。考虑这样的例子:
long t0 = Long.MAX_VALUE;
long t1 = Long.MIN_VALUE;
System.out.println(t1 < t0);
System.out.println(t1 - t0 < 0);
从数学上讲,这两个表达式都是正确的。但是在我们的例子中,我们知道,时间的负值意味着它被溢出了,因此它应该比正数大。当t1在t0之后(t1
更基本的是,如果它读取的是一个无符号的数字,那么负数就比有符号的正数大:而且你是对的,你引用的文档部分似乎有点混乱
然而,重要的文件部分是:
此方法只能用于测量经过的时间,与系统或挂钟时间的任何其他概念无关。返回的值表示纳秒,因为一些固定但任意的起始时间(可能在将来,因此值可能为负值)。Java虚拟机实例中此方法的所有调用都使用相同的源代码;其他虚拟机实例可能使用不同的源
(重点由我补充。)
这意味着,您不能保证代码不会在生成的long值恰好从正值翻转到负值时运行
没有任何东西可以保证这将在300年后发生,它可能在今天发生
目前,我的JVM返回一些数字,如3496793269188,但如果它愿意,它可能返回一些非常接近9223372036854775807的数字(即Long.MAX_VALUE
),这将使从正到负的转换迫在眉睫
因此,您应该采取所有必要的预防措施。数值溢出总是一样的。例如Integer.MAX\u VALUE+1=Integer.MIN\u VALUE
。这也只是一种解决方法。。。584年后,甚至t1-t0@ferrybig那不是真的。正如Javadoc所指出的,nano-time使用一个与系统时间无关的固定起始时间,并且在JVM终止之前不会改变。随系统时钟变化的是system.currentTimeMillis()。只有当出现数字溢出时,纳米时间才会返回“更早”的时间,这一点在大多数的研究中都有解释
long t0 = Long.MAX_VALUE;
long t1 = Long.MIN_VALUE;
System.out.println(t1 < t0);
System.out.println(t1 - t0 < 0);
true
false