Converting Float32 values back to Float64 without introducing nonzero digits at the end?

The issue is that 0.1 is not a number that Float32 (or Float64 or any binary floating point format) can represent. It can only represent numbers that are integer multiples of powers of 2 within certain ranges and with limited precision.

julia> Base.decompose(0.1f0) # Float32(0.1)
(13421773, -27, 1)

julia> 13421773 * 2.0^-27 / 1 # always `/ 1` for Float32, Float64, etc
0.10000000149011612

julia> Float32(13421773 * 2.0^-27 / 1)
0.1f0

julia> BigFloat(0.1e0) # even `Float64` cannot represent 0.1 exactly
0.1000000000000000055511151231257827021181583404541015625

julia> big"0.1" # even `BigFloat` has its limits (adding more precision will reduce but never solve the problem)
0.1000000000000000000000000000000000000000000000000000000000000000000000000000002

So what the computer says is 0.1f0 is actually 13421773 * 2^{-27} = \frac{13421773}{134217728}, which is equal to the number you see when you add extra bits for Float64.

In essence, it is adding zeros to the end of the Float32. But those zeros are added to the binary representation, rather than decimal:

julia> bitstring(0.1f0)
    "00111101110011001100110011001101"
            # ^ start comparing here and to the right

julia> bitstring(Float64(0.1f0))
 "0011111110111001100110011001100110100000000000000000000000000000"
            # ^ start comparing here and to the right

julia> Int(0b110011001100110011001101)
13421773
           # ^ must insert a leading 1 because that's what the these float representations do

(The bits to the left are for the sign and exponent. The exponent bits will be different because the different types use different offsets for their exponents. See Wikipedia for more info.)

So the number it’s giving you is correct and is the number you were always using. It’s just that the Float32 stops printing early because there is no other Float32 that would round that way. Float64 has more precision so can distinguish between more values, so you see the extra digits.

8 Likes