Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Python math is off by .000000000000045 (http://www.velocityreviews.com/forums/t868629-python-math-is-off-by-000000000000045-a.html)

 Alec Taylor 02-22-2012 06:13 PM

Python math is off by .000000000000045

Simple mathematical problem, + and - only:

>>> 1800.00-1041.00-555.74+530.74-794.95

-60.950000000000045

That's wrong.

Proof
http://www.wolframalpha.com/input/?i...B530.74-794.95
-60.95 aka (-(1219/20))

Is there a reason Python math is only approximated? - Or is this a bug?

Thanks for all info,

Alec Taylor

 nn 02-22-2012 06:29 PM

Re: Python math is off by .000000000000045

On Feb 22, 1:13*pm, Alec Taylor <alec.tayl...@gmail.com> wrote:
> Simple mathematical problem, + and - only:
>
> >>> 1800.00-1041.00-555.74+530.74-794.95

>
> -60.950000000000045
>
> That's wrong.
>
> Proofhttp://www.wolframalpha.com/input/?i=1800.00-1041.00-555.74%2B530.74-...
> -60.95 aka (-(1219/20))
>
> Is there a reason Python math is only approximated? - Or is this a bug?
>
> Thanks for all info,
>
> Alec Taylor

I get the right answer if I use the right datatype:

>>> import decimal

>>> D=decimal.Decimal

>>> D('1800.00')-D('1041.00')-D('555.74')+D('530.74')-D('794.95')

Decimal('-60.95')

 Jussi Piitulainen 02-22-2012 06:44 PM

Re: Python math is off by .000000000000045

Alec Taylor writes:

> Simple mathematical problem, + and - only:
>
> >>> 1800.00-1041.00-555.74+530.74-794.95

> -60.950000000000045
>
> That's wrong.

Not by much. I'm not an expert, but my guess is that the exact value
is not representable in binary floating point, which most programming
languages use for this. Ah, indeed:

>>> 0.95

0.94999999999999996

Some languages hide the error by printing fewer decimals than they use
internally.

> Proof
> http://www.wolframalpha.com/input/?i...B530.74-794.95
> -60.95 aka (-(1219/20))
>
> Is there a reason Python math is only approximated? - Or is this a bug?

There are practical reasons. Do learn about "floating point".

There is a price to pay, but you can have exact rational arithmetic in
Python when you need or want it - I folded the long lines by hand
afterwards:

>>> from fractions import Fraction
>>> 1800 - 1041 - Fraction(55574, 100) + Fraction(53074, 100)

- Fraction(79495, 100)
Fraction(-1219, 20)
>>> -1219/20

-61
>>> -1219./20

-60.950000000000003
>>> float(1800 - 1041 - Fraction(55574, 100) + Fraction(53074, 100)

- Fraction(79495, 100))
-60.950000000000003

 Grant Edwards 02-22-2012 08:48 PM

Re: Python math is off by .000000000000045

On 2012-02-22, Alec Taylor <alec.taylor6@gmail.com> wrote:

> Simple mathematical problem, + and - only:
>
>>>> 1800.00-1041.00-555.74+530.74-794.95

> -60.950000000000045
>
> That's wrong.

Oh good. We haven't have this thread for several days.

> Proof
> http://www.wolframalpha.com/input/?i...B530.74-794.95
> -60.95 aka (-(1219/20))
>
> Is there a reason Python math is only approximated?

http://docs.python.org/tutorial/floatingpoint.html

Python uses binary floating point with a fixed size (64 bit IEEE-754
on all the platforms I've ever run across). Floating point numbers
are only approximations of real numbers. For every floating point
number there is a corresponding real number, but 0% of real numbers
can be represented exactly by floating point numbers.

> - Or is this a bug?

No, it's how floating point works.

If you want something else, then perhaps you should use rationals or
decimals:

http://docs.python.org/library/fractions.html
http://docs.python.org/library/decimal.html

--
Grant Edwards grant.b.edwards Yow! What I want to find
at out is -- do parrots know

 Tobiah 02-25-2012 05:56 PM

Re: Python math is off by .000000000000045

> For every floating point
> number there is a corresponding real number, but 0% of real numbers
> can be represented exactly by floating point numbers.

It seems to me that there are a great many real numbers that can be
represented exactly by floating point numbers. The number 1 is an
example.

I suppose that if you divide that count by the infinite count of all
real numbers, you could argue that the result is 0%.

 Tim Wintle 02-25-2012 07:08 PM

Re: Python math is off by .000000000000045

On Sat, 2012-02-25 at 09:56 -0800, Tobiah wrote:
> > For every floating point
> > number there is a corresponding real number, but 0% of real numbers
> > can be represented exactly by floating point numbers.

>
> It seems to me that there are a great many real numbers that can be
> represented exactly by floating point numbers. The number 1 is an
> example.
>
> I suppose that if you divide that count by the infinite count of all
> real numbers, you could argue that the result is 0%.

It's not just an argument - it's mathematically correct.

The same can be said for ints representing the natural numbers, or
positive integers.

However, ints can represent 100% of integers within a specific range,
where floats can't represent all real numbers for any range (except for
the empty set) - because there's an infinate number of real numbers
within any non-trivial range.

Tim

 Terry Reedy 02-25-2012 09:05 PM

Re: Python math is off by .000000000000045

On 2/25/2012 12:56 PM, Tobiah wrote:

> It seems to me that there are a great many real numbers that can be
> represented exactly by floating point numbers. The number 1 is an
> example.

Binary floats can represent and integer and any fraction with a
denominator of 2**n within certain ranges. For decimal floats,
substitute 10**n or more exactly, 2**j * 5**k since if J < k,
n / (2**j * 5**k) = (n * 2**(k-j)) / 10**k and similarly if j > k.

--
Terry Jan Reedy

 jmfauth 02-25-2012 09:25 PM

Re: Python math is off by .000000000000045

>>> (2.0).hex()
'0x1.0000000000000p+1'
>>> (4.0).hex()

'0x1.0000000000000p+2'
>>> (1.5).hex()

'0x1.8000000000000p+0'
>>> (1.1).hex()

'0x1.199999999999ap+0'
>>>

jmf

 Steven D'Aprano 02-25-2012 10:51 PM

Re: Python math is off by .000000000000045

On Sat, 25 Feb 2012 13:25:37 -0800, jmfauth wrote:

>>>> (2.0).hex()

> '0x1.0000000000000p+1'
>>>> (4.0).hex()

> '0x1.0000000000000p+2'
>>>> (1.5).hex()

> '0x1.8000000000000p+0'
>>>> (1.1).hex()

> '0x1.199999999999ap+0'
>>>>
>>>>

> jmf

What's your point? I'm afraid my crystal ball is out of order and I have
no idea whether you have a question or are just demonstrating your
mastery of copy and paste from the Python interactive interpreter.

--
Steven

 Devin Jeanpierre 02-26-2012 02:49 AM

Re: Python math is off by .000000000000045

On Sat, Feb 25, 2012 at 2:08 PM, Tim Wintle <tim.wintle@teamrubber.com> wrote:
> > It seems to me that there Â*are a great many real numbers that can be
> > represented exactly by floating point numbers. Â*The number 1 is an
> > example.
> >
> > I suppose that if you divide that count by the infinite count of all
> > real numbers, you could argue that the result is 0%.

>
> It's not just an argument - it's mathematically correct.

^ this

The floating point numbers are a finite set. Any infinite set, even
the rationals, is too big to have "many" floats relative to the whole,
as in the percentage sense.

----

In fact, any number we can reasonably deal with must have some finite
representation, even if the decimal expansion has an infinite number
of digits. We can work with pi, for example, because there are
algorithms that can enumerate all the digits up to some precision. But
we can't really work with a number for which no algorithm can
enumerate the digits, and for which there are infinitely many digits.
Most (in some sense involving infinities, which is to say, one that is
not really intuitive) of the real numbers cannot in any way or form be
represented in a finite amount of space, so most of them can't be
worked on by computers. They only exist in any sense because it's
convenient to pretend they exist for mathematical purposes, not for
computational purposes.

What this boils down to is to say that, basically by definition, the
set of numbers representable in some finite number of binary digits is
countable (just count up in binary value). But the whole of the real
numbers are uncountable. The hard part is then accepting that some
countable thing is 0% of an uncountable superset. I don't really know
of any "proof" of that latter thing, it's something I've accepted
axiomatically and then worked out backwards from there. But surely
it's obvious, somehow, that the set of finite strings is tiny compared
to the set of infinite strings? If we look at binary strings,
representing numbers, the reals could be encoded as the union of the
two, and by far most of them would be infinite.

Anyway, all that aside, the real numbers are kind of dumb.

-- Devin

All times are GMT. The time now is 01:35 AM.