3

I am intrigued with the following statement found in the documentation of the System.nanoTime() method in Java:

long t0 = System.nanoTime();

...

long t1 = System.nanoTime();

One should use t1 - t0 < 0, not t1 < t0, because of the possibility of numerical overflow.

Source: http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime()

Why is it that t1 < t0 might "overflow"? This is in the Javadocs, but I guess it applies to any language.

Pimgd
  • 5,983
  • 1
  • 30
  • 45

2 Answers2

2

It's not that < might overflow, it's that t2 might overflow.

Examples in hexadecimal, because overflow is obvious in hexadecimal.

Say you call System.nanoTime() and the result is 0x7FFFFFFF00000000. This is very close to the maximum value of a long. This is t1.

A few seconds later you call it again, and get 0x8000000011111111. This is very close to the minimum value of a long - which means it's much smaller than the first value you got! This is t2.

If you checked t2 < t1, you'd get false, because t2 is indeed less than t1.

If you calculate the difference t2 - t1, this also overflows, but it happens that this always cancels out the first overflow (if there was one). The result is 0x0000000111111111 which is the correct time difference. This is greater than 0, so t2 - t1 > 0 returns true.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • @DavidWallace your calculations are wrong then; it will be an issue in or before 2306. Remember it's 2^64 *nano*seconds. – user253751 Jul 15 '14 at 09:44
1

In addition to what immibis said, this source explain the difference between a < b and a-b < 0 with big long:

    long t1 = Long.MAX_VALUE;
    long t2 = Long.MIN_VALUE;
    //should have the same result with small longs, but is different when rotating from max value to min value of Long
    System.out.println(t1 - t2 < 0); //true
    System.out.println(t1 < t2); //false

    //should have the same result
    System.out.println(t1 - t2 > 0); // false
    System.out.println(t1 > t2); //true

    System.out.println(t2 - t1); // 1 => 1 nanosecond of difference

Since time in nanosceond can exceed the "long" size, when the time arrive to the max value, it begins again to the min value. So there is 1 nanesecond of difference between MAX_VALUE end MIN_VALUE

pdem
  • 3,880
  • 1
  • 24
  • 38