Why is 1.5–1.4 == 0.1 false in Java?
What is the Floating-Point precision error?
Computers represent numbers in binary format, which can lead to small errors when some numbers cannot be represented exactly in binary. The floating-point precision error occurs in Java (and other languages) because floating-point numbers are approximations of real numbers.
Floating point numbers are stored in memory according to the IEEE 754 standard. That standard divides floating-point numbers into three parts,
Sign bit: A single bit represents whether the number is positive or negative.
Exponent: To determine the range of the number.
Mantissa: The precision part of the number that holds actual digits.
Example: (1.5–1.4)
Sign bit — 0 (positive)
When we convert 0.4 into binary
01100110011001100110011.... (infinite repeating)
Then 1.4 in binary
1. 01100110011001100110011.... (infinite repeating)
When we write it in normalized scientific notation
1.01100110011001100110011... × 2⁰
Exponent is 0 + 1023 = 1023 -> 01111111111
Mantissa is,
0110011001100110011001100110011001100110011001100110 (fraction part of binary value rounded to 52 bits).
IEEE 754 format of 1.4
0 01111111111 0110011001100110011001100110011001100110011001100110
IEEE 754 format of 1.5
0 01111111111 1000000000000000000000000000000000000000000000000000
When we subtract two binary numbers
1.100000000000000.... – 1.011001100110011.... = 0.000110011001100...
It is approximated to 0.1000000000000000888. it is slightly larger than 0.1
Java implementation to represent IEEE 754 of double
public static String doubleToBinary(double number) {
long bits = Double.doubleToRawLongBits(number);
String binaryString = String.format("%64s", Long.toBinaryString(bits)).replace(' ', '0');
return binaryString.substring(0, 1) + " " + // Sign bit
binaryString.substring(1, 12) + " " + // Exponent (11 bits)
binaryString.substring(12); // Mantissa (52 bits)
}
double number = 1.5;
String binaryRepresentation = doubleToBinary(number);
System.out.println("Decimal: " + number);
System.out.println("IEEE 754 (64-bit) Binary: " + binaryRepresentation);
Output
Decimal: 1.5
IEEE 754 (64-bit) Binary: 0 01111111111 1000000000000000000000000000000000000000000000000000
Conclusion
Java follows the IEEE 754 steps convert, normalize, subtract, and normalize result. 1.4 cannot be perfectly represented binary, then it leads to a small rounding error. That’s why 1.5–1.4!= 0.1 in Java.