Decimal() instead of float?

Michael B. Trausch fd0man at gmail.com
Fri Nov 17 22:51:44 CET 2006


On Fri, 2006-11-17 at 21:25 +0100, Fredrik Lundh wrote:

> > Some of the lat/long pairs that I have used seem to come out fine, but 
> > some do not.  Because the mathmatics used with them involve complex 
> > equations when determining distance and the like, any error gets 
> > massively compounded before a final result is evident.
> 
> sorry, but I don't think you have the slightest idea what you're doing, 
> really.
> 


Sure, I do.  Let's say that I want to work with the latitude 33.6907570.
In Python, that number can not be stored exactly without the aid of
decimal.Decimal().

>>> 33.6907570
33.690756999999998
>>> 

As you can see, it loses accuracy after the 6th decimal place.  That's
not good enough:  I have 8 numbers that need to be exact, and I am only
getting six.  That error will propagate throughout any multiplication or
division problem.  The error compounds itself:

>>> x = 33.6907570
>>> x
33.690756999999998
>>> x*2
67.381513999999996
>>>

Now, observe what happens when you compute it exactly:

>>> from decimal import *
>>> xx = Decimal('33.6907570')
>>> xx
Decimal("33.6907570")
>>> xx*2
Decimal("67.3815140")

Now, observe what happens when you compare the differences
pre-multiplication and post-multiplication:

>>> x = Decimal('33.6907570')
>>> y = Decimal('33.690756999999998')
>>> x - y
Decimal("2E-15")
>>> x = Decimal('67.3815140')
>>> y = Decimal('67.381513999999996')
>>> x - y
Decimal("4E-15")
>>> 

The discrepancy has carried over and been compounded—and this was a
simple multiplication, not something more advanced.

Now, while 4e-15 is a relatively small difference, it is a difference
that will continue to grow due to the inexact nature of the numbers.
This is proof enough that when exact precision is needed, the regular
floating point numbers should not be used.  *I* need exact numbers—plain
and simple.  Those are the requirements for the project I am working on,
and thus I must adhere to them—and they are non-negotiable, which is why
I had opened this thread to begin with.  I wanted to know if there was a
way to simply switch the default mechanism, that's all.  Quite simply,
we're talking about a project where the requirements are absolutely zero
tolerance for error—and it is clearly evident that Python cannot use a
float to store a simple latitude number without causing some error in
the precision.  And it doesn't take a genius to realize that when you
introduce an error—even a minuscule one—into a long sequence of
equations, and those equations involve multiplication and division, the
error becomes compounded and unpredictable.

An example:

>>> 1.1
1.1000000000000001
>>> 1.1+0.1
1.2000000000000002
>>> 1.2
1.2
>>> 1.1*100000
110000.00000000001
>>> 

This does not make any sense at all.  Why is 1.1 == 1.1 and some change,
and 1.1 + 0.1 is off, but 1.2 is not off on its own?  Or, for that
matter, why doesn't the default float type recognize that 1.1*100000 =
110000 without any more floating point?  It is a whole number.

Perhaps you should not make assumptions; I am sure that you have heard
what they do at some point before.  While *some* of the error doesn't
propagate as expected (which is actually a problem in itself—equations
no longer make sense if they are not mathematically balanced!) some
does.  It is unpredictable and can't be tolerated when the numbers must
come out exactly.

    — Mike

--
Michael B. Trausch
                    fd0man at gmail.com
Phone: (404) 592-5746
   Jabber IM: fd0man at livejournal.com

Demand Freedom!  Use open and free protocols, standards, and software!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20061117/d8f9bf15/attachment.html>


More information about the Python-list mailing list