Hi all,
I don’t understand the behavior of isapprox.
julia> -3.03664471426105e-17 ≈ 0.0
false
julia> 1.0 - 3.03664471426105e-17 ≈ 1.0 - 0.0
true
Can someone reproduce/explain what looks like a bug here?
Hi all,
I don’t understand the behavior of isapprox.
julia> -3.03664471426105e-17 ≈ 0.0
false
julia> 1.0 - 3.03664471426105e-17 ≈ 1.0 - 0.0
true
Can someone reproduce/explain what looks like a bug here?
Consider
julia> eps(0.0)
5.0e-324
julia> eps(1.0)
2.220446049250313e-16
and therefore
julia> 1.0 - 3.03664471426105e-17 == 1.0
true
I am very surprised that eps(0.0)
is so small and I don’t understand why nextfloat(0.0)
is 5.0e-324
. Any hint?
This has nothing to do with the value of eps(0.0)
. x ≈ 0.0
will always give false
for x ≠ 0
, because ≈
tests only relative error. If x ≠ 0
, then no significant digits of x
match 0.0
, so the result of x ≈ 0.0
is false
.
In particular, x ≈ y
tests norm(x-y) ≤ sqrt(eps(T))*max(norm(x),norm(y))
with T=typeof(real(x-y))
, which tests whether about half of the significant digits match.
If you call isapprox(x,y)
explicitly, you can pass an atol
argument to instead pass an absolute tolerance, i.e. to test whether norm(x-y) ≤ atol
. But since there is no reasonable way to pick a default value of atol
(it is dimensionful, i.e. it depends on the scale of x
and y
), using ≈
sets atol
to zero.
Note that 1.0 - 1e-10 ≈ 1.0
gives true
, because more than half of the significant digits match 1.0
.
I stand corrected. Thanks for chiming in!
If you are writing tests with the standard Test
module then you can write
@test x ≈ y atol=ε
The @test
macro translates that to isapprox(x, y, atol=ε)
.