public class SimplePrint {
public static void main(String[] args) {
long i = System.currentTimeMillis();
System.out.println(i);
float h = 0.0f;
i -= h;
System.out.println(i);
}
}
The output is:
1477904636902
1477904695296
but when i changed the data type of variable of h
public class SimplePrint {
public static void main(String[] args) {
long i = System.currentTimeMillis();
System.out.println(i);
double h = 0.0f;
i -= h;
System.out.println(i);
}
}
the output is changed:
1477904677513
1477904677513
why is this ???
As is documented in JLS Sec 15.26.2, the compound assignment operator E1 op= E2
is equivalent to
E1 = (T) ((E1) op (E2))
where T is the type of E1.
So, what you're doing in the first case is:
i = (long) (i - 0.0f)
In order to evaluate the -
, i
has to be cast to a float
, as described in JLS Sec 15.18.2:
Binary numeric promotion is performed on the operands (§5.6.2).
and 5.6.2:
Otherwise, if either operand is of type float, the other is converted to float.
The problem is that the value of i
cannot be exactly represented as a float
: because float
only has 24 bits of significand (see here), only values up to around 2^24 (=16777216) can be represented exactly; but the current millis time (on my machine, at least), is around 1477905410000, which is way bigger.
So, you lose precision in converting to float, and that precision can't be recovered when casting back to long
.
Your code is basically:
i = (long) (float) i;
or
i = (long) (double) i;
Now, in Java a float has 23 bits of precision, whilst a double has 52. 1477904677513
has 40 bits in it - 10101100000011001111110111011101010001001
, so when converting to a float you lose the bottom 17 bits, so you see the values change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With