Stdlib: A function to compare two floating-point numbers

Created on 6 Feb 2020  路  5Comments  路  Source: fortran-lang/stdlib

Inspied by Julia, I would like to have a function to compare two floating-point numbers with a tolerance, useful for testing.

elemental function is_approximated_1(x) result(nearly_equal)
    real(dp),intent(in) :: x
    logical :: nearly_equal
    nearly_equal = abs(x) < d_tol
end function is_approximated_1

elemental function is_approximated_2(x,y) result(nearly_equal)
    real(dp),intent(in) :: x,y
    logical :: nearly_equal
    nearly_equal = abs(x-y) < d_tol
end function is_approximated_2

elemental function is_approximated_2_tol(x,y,tol) result(nearly_equal)
    real(dp),intent(in) :: x,y,tol
    logical :: nearly_equal
    nearly_equal = abs(x-y) < tol
end function is_approximated_2

Defining a general name:

interface is_approximated
   module procedure is_approximated_1, is_approximated_2, is_approximated_2_tol
end interface is_approximated

Usage:

real(real64) :: x(5),y(5)

print *,any(is_approximated(x,y))

Most helpful comment

I'd suggest to go with something more general, which allows also relative error. I like quite a lot Numpy's isclose() function which enables to specify both, absolute and relative error. So the interface could be like

elemental function is_close(x, y, reltol, abstol) result(isclosel)
    real(dp),intent(in) :: x, y
    real(dp), intent(in), optional :: reltol, abstol
    logical :: isclose
    isclose = abs(x - y) < reltol * abs(y) + atol
end function is_close

Also, the name is_close() is much shorter than is_approximated().

All 5 comments

I would propose the following API:

is_approximated( x [, tol])
is_approximated( x, y, [, tol])

where tol is optional for both functions. A default tol can be determined with optval.
So, something like:

elemental function is_approximated_2_tol_dp(x,y,tol) result(nearly_equal)
    real(dp),intent(in) :: x,y
    real(dp), intent(in), optional :: tol
    logical :: nearly_equal
    nearly_equal = abs(x-y) < optval(tol, d_tol)
end function is_approximated_2_tol_dp

I would also think that we can drop is_approaximated(x [, tol]) because the user would do explicitely what the second API does implicitely.

This function could be used in the tests of stdlib. A bitwise check with (almost) the same API could also be implemented. See #142 for more discussion.

Finally I may envisage some rebuttals from the community regarding this function because it is a one-line function.

I agree with your suggestion. A simple API is good enough.

I like this function because this comparison always occurs in any tests. A function with a clear purpose makes the code readable. For more precise comparisons, a bit-wise approach is preferred.

I'd suggest to go with something more general, which allows also relative error. I like quite a lot Numpy's isclose() function which enables to specify both, absolute and relative error. So the interface could be like

elemental function is_close(x, y, reltol, abstol) result(isclosel)
    real(dp),intent(in) :: x, y
    real(dp), intent(in), optional :: reltol, abstol
    logical :: isclose
    isclose = abs(x - y) < reltol * abs(y) + atol
end function is_close

Also, the name is_close() is much shorter than is_approximated().

@aradi Julia also uses a similar function. Personally, for a quick comparison, I am using the following function (as suggested by Tamas_Papp).

abs(x - y) < reltol * (1+abs(x)+abs(y))

I suggest is_within.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

certik picture certik  路  5Comments

MuellerSeb picture MuellerSeb  路  8Comments

zbeekman picture zbeekman  路  4Comments

milancurcic picture milancurcic  路  3Comments

leonfoks picture leonfoks  路  9Comments