How does long value fit in float data type in Java without loss of precision. Because if there is loss of precision then the following snippet should have produced
long lMax = Long.MAX_VALUE;
float f = lMax;
System.out.println(lMax == f);
Output
true
The problem is, that for comparison of long
and float
the long
value is being cast to float
, and the same loss of precision occurred as in the assignment...
If you want to "detect" loss of precision, try using BigDecimal
s, something like this:
System.out.println(new BigDecimal(lMax).compareTo(new Bigdecimal(f)));
I know that the constructor BigDecimal(double)
will get the float
cast to double
but there is no precision lost...
For most people long
seems to have more "precision" than float
. However float
has a range of +/-10^38
, which is much larger than long
's...
long lMax = Long.MAX_VALUE;
float f = lMax;
System.out.println( lMax == f );
System.out.println( new BigDecimal( lMax ).compareTo( new BigDecimal( f ) ) );
System.out.println( ( (Float) f ).longValue() == lMax );
System.out.println( ( (Long) lMax ).floatValue() == f );
System.out.printf( "%d, %d%n", ( (Float) f ).longValue(), lMax );
f = --lMax;
System.out.println( lMax == f );
System.out.println( new BigDecimal( lMax ).compareTo( new BigDecimal( f ) ) );
System.out.println( ( (Float) f ).longValue() == lMax );
System.out.println( ( (Long) lMax ).floatValue() == f );
System.out.printf( "%d, %d%n", ( (Float) f ).longValue(), lMax );
Outputs:
true
-1
true
true
9223372036854775807, 9223372036854775807
true
-1
false
true
9223372036854775807, 9223372036854775806
The Binary Numeric Promotion rules in the Java language Specification are key to understanding the behavior of the code snippet in the question. In particular "Otherwise, if either operand is of type float, the other is converted to float."
In the lMax == f
comparison, lMax is converted to float exactly as was done by the float f = lMax
assignment. If you take the same input value, do the same transformation on it twice, and compare the results they will be equal regardless of whether the transformation changed the value or not.
If you want a good demonstration of the precision loss, try this little script when getting system time in milliseconds and converting from long to float:
class Scratch {
public static void main(String[] args) throws InterruptedException {
float currentF;
long currentL;
float lastNewF = 0;
long lastL = System.currentTimeMillis();
long diff;
while (true) {
currentL = System.currentTimeMillis();
currentF = (float) currentL;
if (currentF != lastNewF) {
// we finally got a new "different" float value
lastNewF = currentF;
diff = currentL - lastL;
lastL = currentL;
System.out.println(diff + " milliseconds since we got a new time as float");
}
Thread.sleep(250);
}
}
}
You can see from the output that you are sometimes losing up to 2 minutes of precision:
0 milliseconds since we got a new time as float
46964 milliseconds since we got a new time as float
131054 milliseconds since we got a new time as float
131093 milliseconds since we got a new time as float
131077 milliseconds since we got a new time as float
The value of lMax =9223372036854775807; // It might be different in your JVM.
Value of f = 9.223372E18
Now when you compare lMax == f
, first f is converted to long and then comparison happens. After converting into long, f value is same as lMax.
Even same apply for following code.
long lMax = Long.MAX_VALUE; // value is 9223372036854775807
float f =lMax;
float f2 = 9223372036854775807.5f;
System.out.println(lMax == f);
System.out.println(lMax == f2);
Output
true
true
Here f2 is losing decimal value when compared to long. And long value of f2 is same as lMax.
lMax is a long number. When u assign it to a float it will lose the precision.
float f = lMax;
When you compare a long to a float, internally either long is converted to a float or float is converted to a long. your code
lMax == f
will be similar to
((Float)f).longValue() == lMax
which is 9.223372E18 == 9.223372E18 true
or
((Long)lMax).floatValue() == f
which is 9223372036854775807 == 9223372036854775807 true
in either way the answer is true.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.