[Tutor] greater precision?

Oscar Benjamin oscar.j.benjamin at gmail.com
Mon Oct 29 20:26:09 CET 2012

```On 29 October 2012 10:19, Dave Angel <d at davea.name> wrote:
> On 10/29/2012 05:49 AM, John Collins wrote:
>>
>> Sorry to bother, but if I can squeeze out *at least* 15 sig figs, (30
>> or more would be better!) I'd be a happy camper!
>> XNumbers addon for Excel allows over 200 sig figs by switching to base
>> 256 IIRC. It is this with which I'd like to examine the output of these
>> pyto scripts at finer resolution, if that can be done in python???
>>
>> Best Regards,
>> John Collins.
>>
>>
>
> 18 digits is what you should get if the code is as I describe.  But if
> there are lots of fp operations you're not showing, then an error can
> gradually get larger.  And with any finite precision, you have the risk
> from things such as subtracting two nearly-equal values, which will
> reduce the final precision.

I wouldn't describe it as 18 digits of precision since it fails for
computations that require only 17 digits of precision:

>>> 1e-16
1e-16
>>> 1 + 1e-16 - 1
0.0

>
> If you need more than 18, then go to the Decimal module, which lets you
> set the precision to arbitrary levels.  You will see a substantial
> slowdown, of course, if you set the precision very high.  if that
> becomes a problem, consider CPython 3.3, which has optimized that
> module.  But try not to change too many things at once, as there are
> lots of changes between 2.7 and 3.3.

I don't really understand why so much precision is needed but if I
were trying to improve it I would use the fractions module. The
Fraction type from the fractions module has unlimited precision:

>>> from fractions import Fraction
>>> 1 + Fraction('1e-16')  - 1
Fraction(1, 10000000000000000)
>>> 1 + Fraction('1e-256')  - 1
Fraction(1, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)

To use this you would do the same as for the decimal module: convert
all of your numbers to Fraction type and pass the Fraction objects
into the function that performs computation with them. Of course if
you start out with floats and convert them to fractions then you will
still only have 15 digits of precision so if you really want unlimited
precision you need to convert the numbers to fractions at the point
when their values are known exactly and not use floats anywhere.

This means that your computations are exact but you still need to
choose a precision to output the numbers in decimal (unless you're
happy with fractions as output). If you want 256 digit decimal output
you can do:

>>> import decimal
>>> decimal.getcontext().prec = 256
>>> f = 1 + Fraction('1e-255')
>>> d = decimal.Decimal(f.numerator) / decimal.Decimal(f.denominator)
>>> print(d)
1.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

Oscar
```