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

前端 未结 11 1856

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

相关标签:
11条回答
  • 2020-12-03 03:03

    There is a interesting solution to this by B. Dawson (with C++ code) at "Comparing Floating Point Numbers". His approach relies on strict IEEE representation of two numbers and the enforced lexicographical ordering when said numbers are represented as unsigned integers.

    0 讨论(0)
  • 2020-12-03 03:04

    "Significant figures" in decimal is a matter of adjusting the decimal point and truncating to an integer.

    >>> int(3.1415926 * 10**3)
    3141
    >>> int(1234567 * 10**-3)
    1234
    >>>
    
    0 讨论(0)
  • 2020-12-03 03:10

    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.
    
    0 讨论(0)
  • 2020-12-03 03:13

    I believe your question is not defined well enough, and the unit-tests you present prove it:

    If by 'round to N sig-fig decimal places' you mean 'N decimal places to the right of the decimal point', then the test assert nearlyequal(1e9, 1e9 + 1 , 5) should fail, because even when you round 1000000000 and 1000000001 to 0.00001 accuracy, they are still different.

    And if by 'round to N sig-fig decimal places' you mean 'The N most significant digits, regardless of the decimal point', then the test assert nearlyequal(-1e-9, 1e-9, 5) should fail, because 0.000000001 and -0.000000001 are totally different when viewed this way.

    If you meant the first definition, then the first answer on this page (by Triptych) is good. If you meant the second definition, please say it, I promise to think about it :-)

    0 讨论(0)
  • 2020-12-03 03:14

    Here's a take.

    def nearly_equal(a,b,sig_fig=5):
        return ( a==b or 
                 int(a*10**sig_fig) == int(b*10**sig_fig)
               )
    
    0 讨论(0)
提交回复
热议问题