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)

julia> 1//10 < 0.1
true

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

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: c# - Are there numbers that are not representable in base 10 but can be represented in base 2? - Software Engineering Stack Exchange

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

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.

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.

And for fun

julia> bitstring(3)
"0000000000000000000000000000000000000000000000000000000000000011"

julia> bitstring(1.0)
"0011111111110000000000000000000000000000000000000000000000000000"

julia> bitstring(0.1)
"0011111110111001100110011001100110011001100110011001100110011010"

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.