In tests I’ll like to be able to write the following and the test to pass:
@test aresame(pi, 3.14)
The following works:
@test isapprox(pi, 3.14, atol = 0.005)
But then I need to adjust the absolute tolerance manually.
I need a function to find the “number of significant digits” of a numeric literal and use that.
The following apparently works, but I’m wondering if this already exists?
x_string = string(convert(Float64,x))
length(x_string) - findlast('.',x_string)
tol_digits = min(sigdigs(x), sigdigs(y))
tol = .49*0.1^(tol_digits)
Are there standard functions or a package that does this?
Can this be adapted to make use of the
rtol keyword in
The basic problem here is that the Julia parser does not preserve the number of digits that were used when a literal floating-point value was entered.
The only way I can think of to do this is to define a new type of numeric literal that you construct with a string macro. e.g. you could define a type such that:
@test pi ≈ t"3.14"
t"3.14" constructs a type
TestNumber(3.14, 0.005) and there is an overloaded
val = parse(Float64, s)
parts = split(s, r"\.|[Ee]")
atol = exp10(length(parts) > 1 ? -length(parts) : 0) * 0.5 *
(length(parts) > 2 ? exp10(parse(Int, parts)) : 1.0)
return TestNumber(val, atol)
Base.isapprox(x::Number, t::TestNumber) = isapprox(x, t.val, atol=t.atol)
Base.isapprox(t::TestNumber, x::Number) = isapprox(x, t)
Base.show(io::IO, t::TestNumber) = print(io, t.val, " ± ", t.atol)
So that e.g.
3.14 ± 0.005
3.14 ± 5.0e-5
3.14e-10 ± 5.000000000000001e-15
julia> pi ≈ t"3.14"
julia> pi ≈ t"3.140"
Thank you @stevengj .
Looks like it is a bit more complicated than I imagined.
Could using the
sigdigits parameter of the
round function be useful?
I ask this because I have not understood what exactly the need is.
I would like to “automatically” get the number of significant digits of a numeric literal.
As @stevengj has shown, that is probably not possible in general without using strings or string macros.
Sorry for not being precise.
Could you give some examples of expected result (negative = false or positive = true)?
I have tried the following examples and I don’t know I can’t understand why one is true and one is false.
julia> pi ≈ t"3.1415"
julia> pi ≈ t"3.14159"
ok. understood. depends on whether the next digit is less than or greater than 5
is this equivalent?
Thank you for the suggestion @rocco_sprmnt21 .
Your function captures the idea well. I would prefer it to be symmetric, but that should not be too hard to fix.
Clearly my original post was not precise enough. My main question is if there is already some package (or standard function) that does this.
well … then @steveng’sj solution is right for you, in the absence of a library solution?
maybe something like that if it were available working would be closer to your expectations?
Base.isapprox(x::Number, y::Number, sigdigits:: Bool) =
# here the expressions you used in
return isapprox(x, y, atol = .49*0.1^(tol_digits))`