Is it surprising that the following code outputs a wrong value for startTime?
public class Temp {
public static void main(String args[]){
float duration = (float) 2.0;
long endTime = 1353728995;
long startTime = 0;
startTime = (long) (endTime - duration);
System.out.println(startTime);
}
}
It doesn’t output the wrong value. It just outputs a value that you don’t expect.
The important bit is what happens here:
This is actually evaluated as:
That’s where data is lost. The closest
floatvalue to 1353728995 is 1353729024, and the closestfloatto the result of subtracting 2 is still 1353729024.This all follows the language specification. JLS section 15.8.2 (additive operators) states that binary numeric promotions is applied to the operands.
Section 5.6.2 (binary numeric promotion) starts off like this:
So following those rules, the
longvalue ofendTimeis converted tofloat, and then the subtraction is performed infloatarithmetic.Remember that a
floatonly provides 7 significant figures of accuracy, and the rest is fairly obvious, I hope.Note that without the cast of the result to
long, the compiler makes it clearer what’s going on:That makes it fairly clear that the result is going to be a
float, which should have raised warning bells about how the operation was going to be performed, and what accuracy might be expected.