# Are BigFloats unable to exactly represent 0.1?

`0.1` is a number that can be exactly represented by a `Float16`, or `Float32`, or a `Float64`.
(at least according to how we print them)
But not it would seem (at least according to printing) by a `BigFloat`.

``````julia> parse(Float64, "0.1")
0.1

julia> parse(Float32, "0.1")
0.1f0

julia> parse(Float16, "0.1")
Float16(0.1)

julia> parse(BigFloat, "0.1")
0.1000000000000000000000000000000000000000000000000000000000000000000000000000002
``````

Is this true? Or is it printing wrong?

(I suspect the answer is going to be insightful about floating point representations and printing being round-trip-able with parsing)

2 Likes
``````julia> 1//10 < 0.1
true
``````
8 Likes

As Jeffrey pointed out, this assumption is wrong. Another way to see it:

``````julia> @printf "%.20f" 0.1f0
0.10000000149011611938
julia> @printf "%.50f" 0.1
0.10000000000000000555111512312578270211815834045410
``````
5 Likes

You can also prove by hand that 1/10 is an (infinitely) repeating decimal in base-2, which is why it canâ€™t be represented exactly by binary floating-point with any finite precision: https://softwareengineering.stackexchange.com/a/237018

17 Likes

How does the show method know that we want to see 0.1 and not the real value thatâ€™s stored?

5 Likes

Itâ€™s for the same reason that 0.1 + 0.2 != 0.3 (https://0.30000000000000004.com)

Julia prints the shortest value that uniquely identifies the float in question when parsed back. The algorithm in question is called â€śRyuâ€ť, you can find the julia implementation here.

15 Likes

Is it that we donâ€™t use Ryu for BigFloat but instead use some inferior algorithm?

BigFloat is really a wrapper around the MPFR library, which has its own printing algorithm.

2 Likes

And for fun

``````julia> bitstring(3)
"0000000000000000000000000000000000000000000000000000000000000011"

julia> bitstring(1.0)
"0011111111110000000000000000000000000000000000000000000000000000"

julia> bitstring(0.1)
"0011111110111001100110011001100110011001100110011001100110011010"

``````
5 Likes

BigFloats are binary floating point and it CANNOT exactly represent 0.1 because it is base-2 instead of base-10

I think part of the confusion is that the Julia expression `0.1` is a `Float64` close, but not equal to `1//10`. So `Float64(0.1)` is really the same thing as `0.1`. I try always to be careful to distinguish `0.1` and 1/10 = 0.1 which are different (Julia left and common number right.)

This also implies that `a == 0.30000000000000004` is the correctly rounded answer to the question `0.1 + 0.2 == ?` with rounding error `0.00000000000000002` (and not `0.00000000000000004` as one might think.)

With some custom pretty-printing on top.

2 Likes
7 Likes