Is the Java float to double cast lossy?

I am creating a float value using raw int bits where the mantissa has all bits set to 1. However, casting to double flips the final bit to 0. Why does this happen? From what I've been seeing online, the float to double cast is supposed to preserve the mantissa and exponent since double can accommodate all floats.
class Main {
public static void main(String[] args) {
float f = Float.intBitsToFloat((1 << 23) - 1);
// The following line gives 23 consecutive 1s representing a mantissa with all bits set to 1.
System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
double d = f;
// The following line gives 11100000001111111111111111111111000000000000000000000000000000.
// The mantissa has 22 consecutive 1s not 23 like in the original float
System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));
}
}
I'm using JDK 17, and adding strictfp to the function retains this behavior. I do get a warning saying that strictfp is no longer required.
Answer
These numbers are equal. The conversion is not lossy.
Your float is subnormal. Subnormal floats have an implicit leading bit of 0 rather than 1 in the mantissa.
Your double is normal. It has an implicit leading bit of 1 in the mantissa.
Including the implicit leading bit, both of these numbers have a mantissa with 23 consecutive 1s.
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles