String representations of numbers and approximate equality

wxjmfauth at gmail.com wxjmfauth at gmail.com
Thu Sep 25 08:20:00 CEST 2014


Le jeudi 25 septembre 2014 01:41:42 UTC+2, Dan Stromberg a écrit :
> On Wed, Sep 24, 2014 at 9:54 AM, Chris Angelico <rosuav at gmail.com> wrote:
> 
> > Yes, it's another "how can I see if two numbers are approximately
> 
> > equal" thread, but this time I have a concrete definition of
> 
> > "approximately equal"... and they're Decimals, not floats.
> 
> >
> 
> > I have a number of files (this is an ongoing thing) in which there are
> 
> > two columns of numbers. One of them should be equal to the other times
> 
> > some factor which the program knows from elsewhere. All the numbers
> 
> > are represented as strings of ASCII decimal digits, possibly including
> 
> > a U+002E decimal point. Something like this:
> 
> >
> 
> > # (these are calculated on factor 30)
> 
> > ["0.75", "22.5"]
> 
> > ["0.80", "24"]
> 
> > ["4.73", "142"]
> 
> >
> 
> > The definition of valid is that, within the rounding they've been
> 
> > given, the values are correct. The first two are strictly correct; the
> 
> > third would be 141.9 with full accuracy but 142 is deemed good enough.
> 
> > But this should fail:
> 
> >
> 
> > ["0.1", "10"]
> 
> >
> 
> > 0.1 * 30 should be 3, not 10; and 10 / 30 should be 0.333, not 0.1;
> 
> > therefore this is wrong.
> 
> 
> 
> tolerance = decimal.Decimal('0.1') # I hesitate to call it epsilon
> 
> 
> 
> if abs(decimal1 - decimal2) <= tolerance:
> 
>    print('They are close')
> 
> else:
> 
>    print('They are different')

Basically yes, but...

In the present case, what counts is the confidence interval
of a calculation, not the the precision of the numbers
used for the calculation.

>>> def z(x, y):
...     x, y = float(x), float(y)
...     err = 0.05 * y
...     fac = 30
...     if y - err  <= x * fac < y + err:
...         return 'good enough'
...     else:
...         return 'bad'
...         
>>> z('0.1', '10')
'bad'
>>> z('0.1', '3')
'good enough'
>>> z('4.73', '142')
'good enough'
>>> z('4.729999', '142')
'good enough'
>>> z('4.7300001', '142')
'good enough'
>>> z('4.73', '140')
'good enough'



More information about the Python-list mailing list