Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #73470 > unrolled thread

python 3.44 float addition bug?

Started byFraserL <fraser.long+usenet@NOSPAMgmail.com>
First post2014-06-20 19:57 -0500
Last post2014-06-26 07:53 +0200
Articles 4 on this page of 24 — 15 participants

Back to article view | Back to comp.lang.python


Contents

  python 3.44 float addition bug? FraserL <fraser.long+usenet@NOSPAMgmail.com> - 2014-06-20 19:57 -0500
    Re: python 3.44 float addition bug? FraserL <fraser.long+usenet@gmail.com> - 2014-06-20 20:11 -0500
      Re: python 3.44 float addition bug? Gary Herron <gary.herron@islandtraining.com> - 2014-06-20 18:19 -0700
    Re: python 3.44 float addition bug? Gary Herron <gary.herron@islandtraining.com> - 2014-06-20 18:07 -0700
    Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-21 11:33 +1000
    Re: python 3.44 float addition bug? INADA Naoki <songofacandy@gmail.com> - 2014-06-21 10:06 +0900
    Re: python 3.44 float addition bug? Grant Edwards <invalid@invalid.invalid> - 2014-06-21 14:25 +0000
    Re: python 3.44 float addition bug? Ned Deily <nad@acm.org> - 2014-06-21 12:24 -0700
      Re: python 3.44 float addition bug? buck <workitharder@gmail.com> - 2014-06-23 17:55 -0700
        Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-24 13:26 +1000
        Re: python 3.44 float addition bug? Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2014-06-24 17:30 +1200
        Re: python 3.44 float addition bug? Steven D'Aprano <steve@pearwood.info> - 2014-06-24 06:34 +0000
    Re: python 3.44 float addition bug? Maciej Dziardziel <fiedzia@gmail.com> - 2014-06-25 14:12 -0700
      Re: python 3.44 float addition bug? Steven D'Aprano <steve@pearwood.info> - 2014-06-26 02:56 +0000
        Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-26 13:13 +1000
          Re: python 3.44 float addition bug? Steven D'Aprano <steve@pearwood.info> - 2014-06-26 04:17 +0000
            Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-26 14:41 +1000
        Re: python 3.44 float addition bug? Ben Finney <ben@benfinney.id.au> - 2014-06-26 13:39 +1000
          Re: python 3.44 float addition bug? Steven D'Aprano <steve@pearwood.info> - 2014-06-26 09:15 +0000
            Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-26 19:38 +1000
              Re: python 3.44 float addition bug? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-06-27 02:51 +0000
                Re: python 3.44 float addition bug? Chris Angelico <rosuav@gmail.com> - 2014-06-27 13:24 +1000
                Re: python 3.44 float addition bug? Ian Kelly <ian.g.kelly@gmail.com> - 2014-06-27 10:18 -0600
        Re: python 3.44 float addition bug? Stefan Behnel <stefan_ml@behnel.de> - 2014-06-26 07:53 +0200

Page 2 of 2 — ← Prev page 1 [2]


#73647

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2014-06-27 02:51 +0000
Message-ID<53acdc2d$0$29985$c3e8da3$5496439d@news.astraweb.com>
In reply to#73613
On Thu, 26 Jun 2014 19:38:45 +1000, Chris Angelico wrote:

> On Thu, Jun 26, 2014 at 7:15 PM, Steven D'Aprano <steve@pearwood.info>
> wrote:
>> Here's an error that *cannot* occur with binary floats: the average of
>> two numbers x and y is not guaranteed to lie between x and y!
>>
>>
>> py> from decimal import *
>> py> getcontext().prec = 3
>> py> x = Decimal('0.516')
>> py> y = Decimal('0.518')
>> py> (x + y) / 2
>> Decimal('0.515')
>>
>>
>> Ouch!
> 
> But what you're looking at is also a problem with intermediate rounding,
> as the sum of .516 and .518 can't be represented in 3 digits. 

Exactly. I picked 3 digits because it's much easier to write, and read, a 
3 digit example than a 28 digit example. But the failure here is not a 
property of "too few digits", to be fixed by adding more significant 
digits. No matter how many digits you have, there are some calculations 
which cannot be performed exactly in that many digits.

Although you seem to have missed the critical issue: this is a failure 
mode which *binary floats cannot exhibit*, but decimal floats can. The 
failure being that 

assert x <= (x+y)/2 <= y

may fail if x and y are base 10 floats.

I'm afraid my computational-mathematics skills are not good enough to 
prove this assertion, but Mark Dickinson on the Python-Dev mailing list 
made this claim, and I believe he knows what he is talking about.

https://mail.python.org/pipermail/python-ideas/2014-March/026851.html


If anyone can demonstrate such a failed assertion using floats, I'd love 
to see it.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#73650

FromChris Angelico <rosuav@gmail.com>
Date2014-06-27 13:24 +1000
Message-ID<mailman.11277.1403839456.18130.python-list@python.org>
In reply to#73647
On Fri, Jun 27, 2014 at 12:51 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Although you seem to have missed the critical issue: this is a failure
> mode which *binary floats cannot exhibit*, but decimal floats can. The
> failure being that
>
> assert x <= (x+y)/2 <= y
>
> may fail if x and y are base 10 floats.

No, I didn't miss that; I said that what you were looking at was
*also* caused by intermediate rounding. It happens because .516 + .518
= 1.034, which rounds to 1.03; half of that is .515, which is outside
of your original range - but the intermediate rounding really reduced
the "effective precision" to two digits, by discarding some of the
information in the original. If you accept that your result is now
accurate to only two digits of precision, then that result is within
one ULP of correct (you'll record the average as either .51 or .52,
and your two original inputs are both .52, and the average of .52 and
.52 is clearly .52).

But you're right that this can be very surprising. And it's inherent
to the concept of digits having more range than just "high" or "low",
so there's no way you can get this with binary floats.

ChrisA

[toc] | [prev] | [next] | [standalone]


#73662

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-06-27 10:18 -0600
Message-ID<mailman.11289.1403885983.18130.python-list@python.org>
In reply to#73647
On Thu, Jun 26, 2014 at 9:24 PM, Chris Angelico <rosuav@gmail.com> wrote:
> But you're right that this can be very surprising. And it's inherent
> to the concept of digits having more range than just "high" or "low",
> so there's no way you can get this with binary floats.

For an average of two numbers, I think that's true.  For an average of
more than two numbers, it's possible.

>>> a = 2.0 ** 53 - 1
>>> b = 2.0 ** 53 - 2
>>> a
9007199254740991.0
>>> b
9007199254740990.0
>>> (a + b + b) / 3
9007199254740989.0

[toc] | [prev] | [next] | [standalone]


#73607

FromStefan Behnel <stefan_ml@behnel.de>
Date2014-06-26 07:53 +0200
Message-ID<mailman.11253.1403762045.18130.python-list@python.org>
In reply to#73601
Steven D'Aprano, 26.06.2014 04:56:
> On Wed, 25 Jun 2014 14:12:31 -0700, Maciej Dziardziel wrote:
> 
>> Floating points values use finite amount of memory, and  cannot
>> accurately represent infinite amount of numbers, they are only
>> approximations. This is limitation of float type and applies to any
>> languages that uses types supported directly by cpu. To deal with it you
>> can either use decimal.Decimal type that operates using decimal system
>> and saves you from such surprises
> 
> That's a myth. decimal.Decimal *is* a floating point value, and is 
> subject to *exactly* the same surprises as binary floats, except for one: 
> which Decimal, you can guarantee that any decimal string you enter will 
> appear exactly the same (up to the limit of the current precision).
> 
> For example:
> 
> py> x = Decimal(1)/Decimal(23)
> py> x
> Decimal('0.04347826086956521739130434783')
> py> x*23 == 1
> True
> py> sum( [x]*23 ) == 1  # Surprise!
> False
> 
> py> (Decimal(19)/Decimal(17))*Decimal(17) == 19  # Surprise!
> False

It seems that no-one has mentioned the "fractions" module in this thread
yet. It gives you rational numbers (enumerator/denominator), as supposed to
the limited real numbers that floating point numbers represent.

https://docs.python.org/3/library/fractions.html

There are quite a number of use cases for exact calculations where rational
numbers beat any other solution. For the cases above, for example, you'd
get exact results by design. Or in currency calculations, where you want to
move the rounding to the very end and prevent any loss of precision along
the way (unless you're trying to tweak your account in the right direction,
that is).

Stefan

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web