Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function to determine if two numbers are nearly equal when rounded to n significant decimal digits

I have been asked to test a library provided by a 3rd party. The library is known to be accurate to n significant figures. Any less-significant errors can safely be ignored. I want to write a function to help me compare the results:

def nearlyequal( a, b, sigfig=5 ): 

The purpose of this function is to determine if two floating-point numbers (a and b) are approximately equal. The function will return True if a==b (exact match) or if a and b have the same value when rounded to sigfig significant-figures when written in decimal.

Can anybody suggest a good implementation? I've written a mini unit-test. Unless you can see a bug in my tests then a good implementation should pass the following:

assert nearlyequal(1, 1, 5)  assert nearlyequal(1.0, 1.0, 5)  assert nearlyequal(1.0, 1.0, 5)  assert nearlyequal(-1e-9, 1e-9, 5)  assert nearlyequal(1e9, 1e9 + 1 , 5)  assert not nearlyequal( 1e4, 1e4 + 1, 5)  assert nearlyequal( 0.0, 1e-15, 5 )  assert not nearlyequal( 0.0, 1e-4, 6 )  

Additional notes:

  1. Values a and b might be of type int, float or numpy.float64. Values a and b will always be of the same type. It's vital that conversion does not introduce additional error into the function.
  2. Lets keep this numerical, so functions that convert to strings or use non-mathematical tricks are not ideal. This program will be audited by somebody who is a mathematician who will want to be able to prove that the function does what it is supposed to do.
  3. Speed... I've got to compare a lot of numbers so the faster the better.
  4. I've got numpy, scipy and the standard-library. Anything else will be hard for me to get, especially for such a small part of the project.
like image 402
Salim Fadhley Avatar asked Feb 17 '09 18:02

Salim Fadhley


People also ask

How do you check nearly equal in Python?

assertAlmostEqual() in Python is a unittest library function that is used in unit testing to check whether two given values are almost equal or not.

How do you check if two values are closed in Python?

isclose() method checks whether two values are close to each other, or not. Returns True if the values are close, otherwise False. This method uses a relative or absolute tolerance, to see if the values are close.

How do you write approximately in Python?

In Python, to print the approximately equal symbol, you can use the unicode for approximately equal '\u2245'.


2 Answers

As of Python 3.5, the standard way to do this (using the standard library) is with the math.isclose function.

It has the following signature:

isclose(a, b, rel_tol=1e-9, abs_tol=0.0) 

An example of usage with absolute error tolerance:

from math import isclose a = 1.0 b = 1.00000001 assert isclose(a, b, abs_tol=1e-8) 

If you want it with precision of n significant digits, simply replace the last line with:

assert isclose(a, b, abs_tol=10**-n) 
like image 58
erb Avatar answered Sep 22 '22 04:09

erb


There is a function assert_approx_equal in numpy.testing (source here) which may be a good starting point.

def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True):     """     Raise an assertion if two items are not equal up to significant digits.      .. note:: It is recommended to use one of `assert_allclose`,               `assert_array_almost_equal_nulp` or `assert_array_max_ulp`               instead of this function for more consistent floating point               comparisons.      Given two numbers, check that they are approximately equal.     Approximately equal is defined as the number of significant digits     that agree. 
like image 28
dF. Avatar answered Sep 21 '22 04:09

dF.