Hello everyone,
Is this a bug ? Why is it false for some specific numbers while true for others?
julia> 3 * 1e-5 * 1e5 == 3.0
false
julia> 5 * 1e-5 * 1e5 == 5.0
true
julia> 6 * 1e-5 * 1e5 == 6.0
false
julia> 7 * 1e-5 * 1e5 == 7.0
false
julia> 8 * 1e-5 * 1e5 == 8.0
true
It’s merely a precision issue of floating numbers. Overflow does not occur here.
The reason is, 6e-5 cannot be exactly represented by floating point numbers.
Also, unless really intended, it’s better to approximately compare floating point numbers:
julia> 6*1e-5
6.000000000000001e-5
julia> 6 * 1e-5 * 1e5 ≈ 6.0
true
EDIT: Similar also in Python or any otherIEEE Standard for Floating-Point Arithmetic:
>>> 6 * 1e-5 * 1e5
6.000000000000001
Even ignoring the leading terms, there is no guarantee that 1/x * x == 1. 49e0 and 41f0 are such numbers. For example,
julia> 49e0 / 49e0 # float division by oneself is always 1 (except for 0 and !isfinite)
1.0
julia> 49e0 * (1/49e0) # invert-and-multiply is not the same because the 2 operations accumulate error
0.9999999999999999
julia> 49e0 / complex(49e0) # this issue leads to this annoying quirk for Complex
0.9999999999999999 - 0.0im
julia> using LinearAlgebra
julia> normalize([49e0]) # another invert-and-multiply example
1-element Vector{Float64}:
0.9999999999999999
It’s one of my pet projects to change complex division example to equal 1, but it’s challenging to do it without noticeably degrading performance. I kept getting close and then spilling registers. I’m hoping that better compiler optimization might eventually squeeze it in, but maybe it’s just barely out of reach for current architectures.
you should see if it’s fast on arm. you get twice as many registers there