# what's the precision of fractions.Fraction?

Stefan Sonnenberg-Carstens stefan.sonnenberg at pythonmeister.com
Thu Nov 18 20:08:00 CET 2010

Am 18.11.2010 17:27, schrieb Daniel Fetchinson:
> I do a recursive evaluation of an expression involving fractions and
> unsurprisingly the numerator and denominator grows pretty quickly.
> After 10-20 iterations the number of digits in the numerator and
> denominator (as integers) reaches 80-100. And I'm wondering until what
> point I can trust the result since I'm using fractions.Fraction for
> the whole procedure. Are Fraction's infinite precision? Or will I get
> some sort of an exception if python is not able to represent the
> numerator and/or denominator as integers?
>
> http://www.python.org/dev/peps/pep-3141/ was not very helpful in this
> regard nor was http://docs.python.org/library/fractions.html
>
> Any ideas?
>
> Cheers,
> Daniel
>
I'm not sure what you really want to know.
Fractions are, by their math definition, of unlimited precision.
For example, PI/2 is accurate (with endless precision as PI is a
trancendent number),
but 3.1415926/2 (the decimal representation) is not.
So is fraction.Fraction(1,3) of unlimited precision, thus giving this:

from fractions import Fraction
>>> one_tenth=Fraction(1,10)
>>> a =  one_tenth+one_tenth
>>> a
Fraction(1, 5)
>>> a =  one_tenth+one_tenth+one_tenth
>>> a
Fraction(3, 10)

now compare to standard floats:
>>> one_tenth=1.0/10
>>> a =  one_tenth+one_tenth
>>> a
0.2
>>> a =  one_tenth+one_tenth+one_tenth
>>> a
0.30000000000000004
(this error is caused by the internal representation of floats as binary
numbers, see No. 14 in Python tut).

I think you really want to know, how large numerator/denominator can be.
As python has bignum support (type=long), the only limit is the one your
virtual memory system
offers, which is almost always approx. the amount of ram.

If you need it really *precise*, cast your Fractions into type Decimal:

>>> from decimal import Decimal
>>> one_tenth=Fraction(1,10)
>>> three_tenth = one_tenth*3
>>> d = Decimal(three_tenth.numerator)/Decimal(three_tenth.denominator)
>>> d
Decimal('0.3')

The operator '/' (__div__) is properly over-written.

You can even tweak the precision getcontext().prec by setting it to a
higher value.

Cheers

-------------- next part --------------
A non-text attachment was scrubbed...
Name: stefan_sonnenberg.vcf
Type: text/x-vcard
Size: 223 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20101118/29a6cd73/attachment.vcf>