Why does the floating point representation of 0.1 end in 1?

625 Views Asked by At

I've been writing a decimal to single-precision IEEE754 floating-point converter, and I found a few discrepancies with numbers like 0.1 and 0.2

Let's take 0.1, the first step would be converting it into a simple binary representation (multiplying the fractional part by 2 and taking the integral part) This gives me a well-known recurring binary pattern (001100110011...)

The final binary representation of 0.1 (up to 26-bits) is 0 . 00 0110 0110 0110 0110 0110 0110.

To fit it into a 32-bit floating-point number, the next step is to normalize it by shifting the decimal point 4 times to the right, removing the leading 1., and truncating it to 23 bits. This leaves me with 10011001100110011001100. Most programming languages give me 10011001100110011001101 (with the last bit 1 instead of 0). What am I doing wrong here?

1

There are 1 best solutions below

0
chux - Reinstate Monica On

... removing the leading 1., and truncating it to 23 bits.

Wrong operation: round, not truncate. Wrong order of operations - round, then remove the leading 1.

... still have no idea how it gets flipped though

The infinite exact binary answer rounded to the closest float.


With common float32, the significand is 24-bit*1. Conversion of values with more than 24-bits is usually a round*2, not truncate. The remaining bits were 110_0110_...

        123 4567 8901 2345 6789 0123 4
0 . 00 0110 0110 0110 0110 0110 0110 0110 0110 ...
        ^----------------------------^
0 . 00 0110 0110 0110 0110 0110 0110 1 rounded
         10 0110 0110 0110 0110 0110 1 encoded 23-bits

The rounding happens before the leading bit is removed as part of the encoding as the most significant bit place may change.


Notes:

0.000110011001100110011001100           (binary) = 0.0999999940395355224609375000 (decimal)
0.0001100110011001100110011001100110... (binary) = 0.1                            (decimal)
0.000110011001100110011001101 (closer)  (binary) = 0.1000000014901161193847656250 (decimal)
 
        

*1 Most significant 1 bit implied, 23-bits explicitly coded.
*2 Round to nearest, ties to even.