I hope this question is not silly. When converting a `Float32`

value back to `Float64`

, I get something like this:

```
julia> Float64(Float32(0.1))
0.10000000149011612
```

Is there a way to obtain exactly 0.1 without having the nonzero digits coming at the end? Thank you!

Edit:

The purpose is not to print a single value but to do a bunch of computation based on data loaded from files that are in Float32. It’s not something crucial but I am still curious.

This is just how binary floating-point works. What is your actual issue? Do you know about the Printf stdlib, perhaps it would be useful for you.

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