Why is 1.5–1.4 == 0.1 false in Java?

Rukmal Senavirathne
2 min read3 days ago

--

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.

--

--

Rukmal Senavirathne
Rukmal Senavirathne

Written by Rukmal Senavirathne

Senior Software Engineer at GTN. Graduated from the Department of Computer Science and Engineering at the University of Moratuwa.

No responses yet