# 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:
...
>>> z('0.1', '10')
>>> 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'

```