如何比较两个纳米时间值?[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