[Tutor] very odd math problem

Knacktus knacktus at googlemail.com
Fri Mar 11 07:00:01 CET 2011


Am 11.03.2011 06:05, schrieb Steven D'Aprano:
> Alex Hall wrote:
>> Hi all,
>> I am trying to get a list of ordered pairs from the below function. In
>> my code, evaluate is more exciting, but the evaluate here will at
>> least let this run. The below runs fine, with one exception: somehow,
>> it is saying that -2+2.0 is 4.x, where x is a huge decimal involving
>> E-16 (in other words, a really tiny number). Does anyone have any idea
>> what is going on here?
>
>
> Let's reword the description of the problem...
>
> "2.0 - 2 is a really tiny number close to 4e-16"
>
> Welcome to the wonders of floating point maths! Repeat after me:
>
> Floats are not real numbers... floats are not real numbers...
> floats are not real numbers... everything you learned about
> arithmetic in school only *approximately* applies to floats.
>
> Half :) and half :(
>
> First off, anything involving e-16 isn't a "huge decimal", it's a tiny
> decimal, very close to zero, no matter what the x is:
>
> 0.0000000000000004x
>
> Also, although you say "-2 + 2.0" in a comment, that's not actually what
> you calculate. I know this even though I don't know what you calculate,
> because I can test -2 + 2.0 and see that it is exactly zero:
>
>  >>> -2 + 2.0 == 0
> True
>
> Somewhere in your calculation you're probably calculating something
> which *looks* like 2.0 but isn't. Here's an example:
>
>  >>> x = 2 + 1e-14
>  >>> print(x)
> 2.0
>  >>> x == 2.0
> False
>
> but you can see the difference by printing the float with more decimal
> places than shown by the default view:
>
>  >>> repr(x)
> '2.00000000000001'
>
>
> Another problem: you calculate your values by repeated addition. This is
> the wrong way to do it, because each addition has a tiny little error,
> and repeating them just compounds error upon error. Here's an example:
>
>
>  >>> x = 0.0
>  >>> for i in range(10):
> ... x += 0.1
> ...
>  >>> x == 1.0
> False
>  >>> print(x)
> 1.0
>  >>> repr(x)
> '0.99999999999999989'
>
>
> The right way is to do it like this:
>
>
>  >>> x = 0.0
>  >>> for i in range(1, 11):
> ... x = i*0.1
> ...
>  >>> x == 1.0
> True
>
> This ensures that errors don't compound.
>
>
> Some further resources:
>
> http://floating-point-gui.de/
> http://introcs.cs.princeton.edu/91float/
>
> David Goldberg used to have a fantastic (although quite technical)
> discussion of floating point issues, "What Every Computer Scientist
> Should Know About Floating-Point Arithmetic":
>
> http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> Unfortunately, since Oracle bought Sun, they've removed the article.
> Bastards.
>
> If you can find a copy of Apple's old "Apple Numeric Manual" (2nd
> Edition), it has a fantastic introduction by William Kahan. Even though
> the book is about Apple's SANE, a lot will apply to other floating point
> systems as well.
>
> Google on William Kahan and read his stuff :)
>
>
>
Damn, you're fast!! ;-))


More information about the Tutor mailing list