2
votes

In the Julia 1.0.0 REPL I get the following results:

# Line 1: This make sense.  I did not expect a Float64 to equal a BigFloat.
julia> 26.1 == big"26.1"
false

# Line 2: This surprised me when Line 1 is considered.  Again, like Line 1, I 
# did not expect a Float64 to equal an equivalent BigFloat.
julia> 26.0 == big"26.0"
true

# Line 3: This I expected based on Line 1 behavior.
julia> 26.1 - 0.1 == big"26.1" - 0.1
false

# Line 4: This surprised me based on Line 1 behavior, but it might be 
# explained based on Line 2 behavior.  It seems to imply that if a Float64 
# can be converted to an Integer it will compare equal to an equivalent BigFloat.
julia> 26.1 - 0.1 == big"26.1" - big"0.1"
true

It seems that Julia is doing something under the hood here for equality comparisons with Float64 and BigFloat that makes lines 2 and 4 true, while lines 1 and 3 are false. Any suggestions?

The Julia doc regarding "==" does not seem to cover this kind of thing: https://docs.julialang.org/en/v1/base/math/#Base.:==

EDIT: Based on a helpful comment by @EPo below, it is easy to make all comparisons above come out to true. For example, Line 1 and Line 3 are true below, though they were false above:

# Line 1 is now true.
julia> 26.1 ≈ big"26.1"
true

# Line 3 is now true.
julia> 26.1 - 0.1 ≈ big"26.1" - 0.1
true
2
I don't think Julia is doing anything under the hood but you are running into exploringbinary.com/… - carstenbauer
try use ≈ (approx equality, \approx<tab>) - Evgeny
@crstnbr, I now see from the accepted answer below that you are right. I did not guess that 26.0 would be represented so accurately in Float64. - Julia Learner
@EPo, Thanks for suggestion. - Julia Learner

2 Answers

7
votes

Some floating point number can be represented exactly (26.0) but not all, for instance:

julia> using Printf
julia> @printf("%.80f",26.0)
26.00000000000000000000000000000000000000000000000000000000000000000000000000000000
julia> @printf("%.80f",0.1)
0.10000000000000000555111512312578270211815834045410156250000000000000000000000000

The decimals 0.5, 0.25, 0.125 for example can be also represented exactly with the binary based floating point representation. So for instance you have:

julia> 26.125 - 0.125 == big"26.125" - 0.125
true

But 0.1 is a periodic number in the binary system, so it is rounded.

julia> bitstring(0.1)
"0011111110111001100110011001100110011001100110011001100110011010"

The last 52 bits represent the fraction in binary. (https://en.wikipedia.org/wiki/Double-precision_floating-point_format)

1
votes

The reason they are not the same is because they are not the same

julia> using Printf
julia> string(BigFloat("26.1")-BigFloat("26"))
"1.000000000000000000000000000000000000000000000000000000000000000000000000000553e-01"
julia> @printf("%.17e",Float64(26.1)-Float64(26))
1.00000000000001421e-01
julia> Float64(26.1)-Float64(26) > BigFloat("26.1")-BigFloat("26")
true