When I was reading System.nanoTime() API in Java. I found this line:
one should use t1 - t0 < 0, not t1 < t0, because of the possibility of numerical overflow.
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime()
To compare two nanoTime values
long t0 = System.nanoTime(); ... long t1 = System.nanoTime();one should use t1 - t0 < 0, not t1 < t0, because of the possibility of numerical overflow.
I want to know why t1 - t0 < 0 is preferable way to prevent overflow.
Because I read from some other thread that A < B is more preferable than A - B < 0.
Java Integer compareTo() - why use comparison vs. subtraction?
These two things make contradiction.
The Nano time is not a 'real' time, it is just a counter that increments starting from some unspecified number when some unspecified event occurs (maybe the computer is booted up).
It will overflow, and become negative at some point. If your t0 is just before it overflows (i.e. very large positive), and your t1 is just after (very large negative number), then t1 < t0 (i.e. your conditions are wrong because t1 happened after t0).....
But, if you say t1 - t0 < 0, well, the magic is that a for the same overflow (undeflow) reasons (very large negative subtract a very large positive will underflow), the result will be the number of nanoseconds that t1 was after t0..... and will be right.
In this case, two wrongs really do make a right!
t0 - t1 < 0 is better then t0 < t1 when we are sure that real difference of values (before overflow) is not grater than half or size of set that contains all possible values.
For nanoseconds it will be approximately 292 years (nanoseconds are stored in long and half of long size is 2^64/2 = 2^63 nanoseconds ~= 292 years).
So for time samples separated with less then 292 years we should use t0 - t1 < 0 to get correct results.
To better visualize it lets say that cycle contains 8 possible values which are -4, -3, -2, -1 ,0, 1, 2, 3.
So timeline can look like
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, ..
Lets take a look how t0 - t1 < 0 and t0 < t1 will behave for values where difference will be and wont be greater than 4 (half of cycle size, and -4 is minimal value which means it can be minimal result for calculating delta). Notice that only t0 - t1 < 0 will give correct results when t1 overflows
delta = 1 with overflow of bigger value (notice: we don't make lesser value overflow because it would mean that both values are in the same cycle so calculations would be same as if there wouldn't be any overflow)
- real values:
t0 = 3t1 = 4 - overflowed:
t0 = 3t1 = -4 t0 < t1==>3 < -4-> falset0 - t1 < 0==>3 - (-4) < 0==>-1 < 0(7 overflows to -1) true
so only for
t0 - t1 < 0we got correct result despite or maybe thanks to overflow.- real values:
delta = 1 but this time no overflow
a) positive values
t0 = 2,t1 = 32 < 3true2 - 3 < 0==>-1 < 0true
b) negative values
t0 = -4,t1 = -3-4 < -3true-4 - (-3) < 0==>-1 < 0true
for rest of cases where real delta = 1 we will also get correct results for both
t0 < t1andt0 - t1 < 0tests (t0 - t1will be always-1)delta = 3 (almost half of cycle)
a1) with overflow of bigger value
- real values:
t0 = 3t1 = 6 - overflowed:
t0 = 3t1 = -2 t0 < t1==>3 < -2-> falset0 - t1 < 0==>3 - (-2) < 0==>-3 < 0(5 overflows to -3) true
a2) another case with overflow
- real values:
t0 = 2t1 = 5 - overflowed:
t0 = 2t1 = -3 t0 < t1==>2 < -3-> falset0 - t1 < 0==>2 - (-3) < 0==>-3 < 0(again 5 overflows to -3) true
So again onlyt0 - t1 < 0gave correct result.b) without overflow
t0 - t1will always be equal to-3(-delta) so this will always be giving correct result.t0 < t1will also give correct resilt- real values:
t0 = -1t1 = 2 t0 < t1==>-1 < 2-> truet0 - t1 < 0==>-1 - 2 < 0==>-3 < 0true
- real values:
delta = 4 result of
t0 - t1will always be equal to-4so it will also be<0.examples with overflow
a1)- real values:
t0 = 0t1 = 4 - overflowed:
t0 = 0t1 = -4 t0 < t1==>0 < -4-> falset0 - t1 < 0==>0 - (-4) < 0==>-4 < 0(4 overflows to -4) true
a2)
- real values:
t0 = 1t1 = 5 - overflowed:
t0 = 1t1 = -3 t0 < t1==>1 < -4-> falset0 - t1 < 0==>1 - (-3) < 0==>-4 < 0(4 overflows to -4) true
So again only
t0 - t1 < 0give correct results.Examples without overflow obviously will be correct for both tests.
- real values:
delta = 5 (and more)
a1) with overflow
(minimal value tor t0 is -1 so lets start with it)- real values:
t0 = -1t1 = 4 - overflowed:
t0 = -1t1 = -4 t0 < t1==>-1 < -4-> falset0 - t1 < 0==>-1 - (-4) < 0==>3 < 0false
a2) with overflow
- real values:
t0 = 1t1 = 6 - overflowed:
t0 = 1t1 = -2 t0 < t1==>1 < -2-> falset0 - t1 < 0==>1 - (-2) < 0==>3 < 0false both tests failed
b1) without overflow
t0 = -4,t1 = 1-4 < 1true-4 - 1 < 0==>3 < 0(-5 overflows to 3) false
- real values:
+-------------+-----------------------------+----------------------------+
| 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 | - | - | + | - |
+-------------+------------+----------------+-----------+----------------+
The quote from the API is actually:
Differences in successive calls that span greater than approximately 292 years (2^63 nanoseconds) will not accurately compute elapsed time due to numerical overflow.
If t0 and t1 are measured 292 years apart you will experience numerical overflow. Otherwise either the comparison or the subtraction will work just fine.
Use any method.
It will be no difference in the nearest 290 years.
Your program (and even Java itself) will not live so long.
来源:https://stackoverflow.com/questions/18414059/why-should-i-use-t1-t0-0-not-t1-t0-when-using-system-nanotime-in-java