finding out the precision of floats

Bart Ogryczak B.Ogryczak at gmail.com
Wed Feb 28 06:38:02 EST 2007


On Feb 27, 7:58 pm, "Arnaud Delobelle" <arno... at googlemail.com> wrote:
> On 27 Feb, 14:09, "Bart Ogryczak" <B.Ogryc... at gmail.com> wrote:
>
> > On Feb 27, 1:36 pm, Facundo Batista <facu... at taniquetil.com.ar> wrote:
>
> > > Arnaud Delobelle wrote:
> > > > (and I don't want the standard Decimal class :)
>
> > > Why?
>
> > Why should you? It only gives you 28 significant digits, while 64-bit
> > float (as in 32-bit version of Python) gives you 53 significant
> > digits. Also note, that on x86 FPU uses 80-bit registers. An then
> > Decimal executes over 1500 times slower.
>
> Actually 28 significant digits is the default, it can be set to
> anything you like.  Moreover 53 significant bits (as this is what 53
> counts) is about 16 decimal digits.

My mistake.

> > >>> from timeit import Timer
> > >>> t1 = Timer('(1.0/3.0)*3.0 - 1.0')
> > >>> t2 = Timer('(Decimal(1)/Decimal(3))*Decimal(3)-Decimal(1)',
>
> > 'from decimal import Decimal')>>> t2.timeit()/t1.timeit()
>
> > 1621.7838879255889
>
> Yes. The internal representation of a Decimal is a tuple of one-digit
> strings!
> This is one of the reasons (by no means the main) why I decided to
> write my own class.

Why not GMP?

> > If that's not enough to forget about Decimal, take a look at this:
>
> > >>> (Decimal(1)/Decimal(3))*Decimal(3) == Decimal(1)
> > False
> > >>> ((1.0/3.0)*3.0) == 1.0
>
> > True
>
> OTOH float is not the panacea:

My point is, that neither is Decimal. It doesn't solve the problem,
creating additional problem with efficiency.

> >>> 0.1+0.1+0.1==0.3
> False
> >>> 3*0.1==0.3
>
> False
>
> Decimals will behave better in this case.

Decimal will work fine as long as you deal only with decimal numbers
and the most basic arithmetic. Any rational number with base that is
not power of 10, or any irrational number won't have an exact
representation. So as long as you're dealing with something like
invoices, Decimal does just fine. When you start real calculations,
not only scientific, but even financial ones[1], it doesn't do any
better then binary float, and it's bloody slow.

[1] eg. consider calculating interests rate, which often is defined as
math.pow(anualRate,days/365.0). It's not rational number (unless days
happen to be mutliple of 365), therefore has no exact representation.
BTW, math.* functions do not return Decimals.





More information about the Python-list mailing list