Is there a function to test floating point approximate equality in python? Something like,
def approx_equal(a, b, tol): return abs(a - b) < tol
My use case is similar to how Google's C++ testing library, gtest.h, defines EXPECT_NEAR
.
Here is an example:
def bernoulli_fraction_to_angle(fraction): return math.asin(sqrt(fraction)) def bernoulli_angle_to_fraction(angle): return math.sin(angle) ** 2 def test_bernoulli_conversions(): assert(approx_equal(bernoulli_angle_to_fraction(pi / 4), 0.5, 1e-4)) assert(approx_equal( bernoulli_fraction_to_angle(bernoulli_angle_to_fraction(0.1)), 0.1, 1e-4))
In the case of floating-point numbers, the relational operator (==) does not produce correct output, this is due to the internal precision errors in rounding up floating-point numbers.
This is a fast initial check. if both numbers are any of +0, -0 or subnormal, numbers are equal. if exponents have difference exactly 1, shift correctly the fraction from one of the numbers. If difference of 2 fractions is small, numbers are equal.
This is because floating point values are not precise, and small rounding errors in the floating point operands may cause unexpected results.
How To Compare Floats in Python. If abs(a - b) is smaller than some percentage of the larger of a or b , then a is considered sufficiently close to b to be "equal" to b . This percentage is called the relative tolerance. You can specify the relative tolerance with the rel_tol keyword argument of math.
math.isclose
.numpy.allclose
.numpy.testing.assert_allclose
Another approach is to compute the relative change (or relative difference) of the two numbers, which is "used to compare two quantities while taking into account the 'sizes' of the things being compared". The two formulas mentioned in the Wikipedia article could be used in comparisons like the following in Python, which also handle cases where one or both of the values being compared are zero:
def approx_equal(a, b, tol): return abs(a-b) <= max(abs(a), abs(b)) * tol def approx_equal(a, b, tol): return abs(a-b) <= (abs(a)+abs(b))/2 * tol
The calculated value in either case is a unitless fraction. In the first case the baseline value is the maximum absolute value of the two numbers and in the second it's their mean absolute value. The article discusses each in more detail as well as their pros and cons. The latter can turned into a percentage difference if multiplied by 100 before the comparison (with tol
becoming a percentage value). Note that the article suggests that if the changing value "is a percentage itself, it is better to talk about its change by using percentage points" — i.e. absolute change.
Both of these methods (obviously) require a little more computation than simply taking the absolute value of the difference of the two numbers, which might be a consideration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With