Maths error

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rory Campbell-Lange

    #1

    Maths error

    >>(1.0/10.0) + (2.0/10.0) + (3.0/10.0)
    0.6000000000000 0009
    >>6.0/10.0
    0.5999999999999 9998

    Is using the decimal module the best way around this? (I'm expecting the first
    sum to match the second). It seem anachronistic that decimal takes strings as
    input, though.

    Help much appreciated;
    Rory
    --
    Rory Campbell-Lange
    <rory@campbel l-lange.net>
    <www.campbell-lange.net>
  • Bjoern Schliessmann

    #2
    Re: Maths error

    Rory Campbell-Lange wrote:
    Is using the decimal module the best way around this? (I'm
    expecting the first sum to match the second). It seem
    anachronistic that decimal takes strings as input, though.
    What's your problem with the result, or what's your goal? Such
    precision errors with floating point numbers are normal because the
    precision is limited technically.

    For floats a and b, you'd seldom say "if a == b:" (because it's
    often false as in your case) but rather
    "if a - b < threshold:" for a reasonable threshold value which
    depends on your application.

    Also check the recent thread "bizarre floating point output".

    Regards,


    Björn

    --
    BOFH excuse #333:

    A plumber is needed, the network drain is clogged

    Comment

    • Gabriel Genellina

      #3
      Re: Maths error

      At Monday 8/1/2007 19:20, Bjoern Schliessmann wrote:
      >Rory Campbell-Lange wrote:
      >
      Is using the decimal module the best way around this? (I'm
      expecting the first sum to match the second). It seem
      anachronistic that decimal takes strings as input, though.
      >[...]
      >Also check the recent thread "bizarre floating point output".
      And the last section on the Python Tutorial "Floating Point
      Arithmetic: Issues and Limitations"


      --
      Gabriel Genellina
      Softlab SRL






      _______________ _______________ _______________ _____
      Preguntá. Respondé. Descubrí.
      Todo lo que querías saber, y lo que ni imaginabas,
      está en Yahoo! Respuestas (Beta).
      ¡Probalo ya!


      Comment

      • Dan Bishop

        #4
        Re: Maths error

        On Jan 8, 3:30 pm, Rory Campbell-Lange <r...@campbel l-lange.netwrote:
        >(1.0/10.0) + (2.0/10.0) + (3.0/10.0)
        0.6000000000000 0009
        >6.0/10.0
        0.5999999999999 9998
        >
        Is using the decimal module the best way around this? (I'm expecting the first
        sum to match the second).
        Probably not. Decimal arithmetic is NOT a cure-all for floating-point
        arithmetic errors.
        >>Decimal(1) / Decimal(3) * Decimal(3)
        Decimal("0.9999 999999999999999 999999999")
        >>Decimal(2).sq rt() ** 2
        Decimal("1.9999 999999999999999 99999999")
        It seem anachronistic that decimal takes strings as
        input, though.
        How else would you distinguish Decimal('0.1') from
        Decimal('0.1000 000000000000055 511151231257827 021181583404541 015625')?

        Comment

        • Nick Maclaren

          #5
          Re: Maths error


          |Rory Campbell-Lange wrote:
          |>
          | Is using the decimal module the best way around this? (I'm
          | expecting the first sum to match the second). It seem
          | anachronistic that decimal takes strings as input, though.

          As Dan Bishop says, probably not. The introduction to the decimal
          module makes exaggerated claims of accuracy, amounting to propaganda.
          It is numerically no better than binary, and has some advantages
          and some disadvantages.

          |Also check the recent thread "bizarre floating point output".

          No, don't. That is about another matter entirely, and will merely
          confuse you. I have a course on computer arithmetic, and am just
          now writing one on Python numerics, and confused people may contact
          me - though I don't guarantee to help.


          Regards,
          Nick Maclaren.

          Comment

          • Carsten Haese

            #6
            Re: Maths error

            On Tue, 2007-01-09 at 11:38 +0000, Nick Maclaren wrote:
            |Rory Campbell-Lange wrote:
            |>
            | Is using the decimal module the best way around this? (I'm
            | expecting the first sum to match the second). It seem
            | anachronistic that decimal takes strings as input, though.
            >
            As Dan Bishop says, probably not. The introduction to the decimal
            module makes exaggerated claims of accuracy, amounting to propaganda.
            It is numerically no better than binary, and has some advantages
            and some disadvantages.
            Please elaborate. Which exaggerated claims are made, and how is decimal
            no better than binary?

            -Carsten


            Comment

            • Tim Peters

              #7
              Re: Maths error

              [Rory Campbell-Lange]
              >>Is using the decimal module the best way around this? (I'm
              >>expecting the first sum to match the second). It seem
              >>anachronist ic that decimal takes strings as input, though.
              [Nick Maclaren]
              >As Dan Bishop says, probably not. The introduction to the decimal
              >module makes exaggerated claims of accuracy, amounting to propaganda.
              >It is numerically no better than binary, and has some advantages
              >and some disadvantages.
              [Carsten Haese]
              Please elaborate. Which exaggerated claims are made,
              Well, just about any technical statement can be misleading if not qualified
              to such an extent that the only people who can still understand it knew it
              to begin with <0.8 wink>. The most dubious statement here to my eyes is
              the intro's "exactness carries over into arithmetic". It takes a world of
              additional words to explain exactly what it is about the example given (0.1
              + 0.1 + 0.1 - 0.3 = 0 exactly in decimal fp, but not in binary fp) that
              does, and does not, generalize. Roughly, it does generalize to one
              important real-life use-case: adding and subtracting any number of decimal
              quantities delivers the exact decimal result, /provided/ that precision is
              set high enough that no rounding occurs.
              and how is decimal no better than binary?
              Basically, they both lose info when rounding does occur. For example,
              >>import decimal
              >>1 / decimal.Decimal (3)
              Decimal("0.3333 333333333333333 333333333")
              >>_ * 3
              Decimal("0.9999 999999999999999 999999999")

              That is, (1/3)*3 != 1 in decimal. The reason why is obvious "by eyeball",
              but only because you have a lifetime of experience working in base 10. A
              bit ironically, the rounding in binary just happens to be such that (1/3)/3
              does equal 1:
              >>1./3
              0.3333333333333 3331
              >>_ * 3
              1.0

              It's not just * and /. The real thing at work in the 0.1 + 0.1 + 0.1 - 0.3
              example is representation error, not sloppy +/-: 0.1 and 0.3 can't be
              /represented/ exactly as binary floats to begin with. Much the same can
              happen if you instead you use inputs exactly representable in base 2 but
              not in base 10 (and while there are none such if precision is infinite,
              precision isn't infinite):
              >>x = decimal.Decimal (1) / 2**90
              >>print x
              8.0779356694631 60887416100508E-28
              >>print x + x + x - 3*x # not exactly 0
              1E-54

              The same in binary f.p. is exact, because 1./2**90 is exactly representable
              in binary fp:
              >>x = 1. / 2**90
              >>print x # this displays an inexact decimal approx. to 1./2**90
              8.07793566946e-028
              >>print x + x + x - 3*x # but the binary arithmetic is exact
              0.0

              If you boost decimal's precision high enough, then this specific example is
              also exact using decimal; but with the default precision of 28, 1./2**90
              can't be represented exactly in decimal to begin with; e.g.,
              >>decimal.Decim al(1) / 2**90 * 2**90
              Decimal("0.9999 999999999999999 999999999")

              All forms of fp are subject to representation and rounding errors. The
              biggest practical difference here is that the `decimal` module is not
              subject to representation error for "natural" decimal quantities, provided
              precision is set high enough to retain all the input digits. That's worth
              something to many apps, and is the whole ball of wax for some apps -- but
              leaves a world of possible "surprises" nevertheless.

              Comment

              • Bjoern Schliessmann

                #8
                Re: Maths error

                Nick Maclaren wrote:
                No, don't. That is about another matter entirely,
                It isn't.

                Regards,


                Björn

                --
                BOFH excuse #366:

                ATM cell has no roaming feature turned on, notebooks can't connect

                Comment

                • Nick Maclaren

                  #9
                  Re: Maths error


                  In article <Xns98B384E126F 4Ctim111one@216 .196.97.136>,
                  Tim Peters <tim.one@comcas t.netwrites:
                  |>
                  |Well, just about any technical statement can be misleading if not qualified
                  |to such an extent that the only people who can still understand it knew it
                  |to begin with <0.8 wink>. The most dubious statement here to my eyes is
                  |the intro's "exactness carries over into arithmetic". It takes a world of
                  |additional words to explain exactly what it is about the example given (0.1
                  |+ 0.1 + 0.1 - 0.3 = 0 exactly in decimal fp, but not in binary fp) that
                  |does, and does not, generalize. Roughly, it does generalize to one
                  |important real-life use-case: adding and subtracting any number of decimal
                  |quantities delivers the exact decimal result, /provided/ that precision is
                  |set high enough that no rounding occurs.

                  Precisely. There is one other such statement, too: "Decimal numbers can
                  be represented exactly." What it MEANS is that numbers with a short
                  representation in decimal can be represented exactly in decimal, which
                  is tautologous, but many people READ it to say that numbers that they
                  are interested in can be represented exactly in decimal. Such as pi,
                  sqrt(2), 1/3 and so on ....

                  | and how is decimal no better than binary?
                  |>
                  |Basically, they both lose info when rounding does occur. For example,

                  Yes, but there are two ways in which binary is superior. Let's skip
                  the superior 'smoothness', as being too arcane an issue for this group,
                  and deal with the other. In binary, calculating the mid-point of two
                  numbers (a very common operation) is guaranteed to be within the range
                  defined by those numbers, or to over/under-flow.

                  Neither (x+y)/2.0 nor (x/2.0+y/2.0) are necessarily within the range
                  (x,y) in decimal, even for the most respectable values of x and y.
                  This was a MAJOR "gotcha" in the days before binary became standard,
                  and will clearly return with decimal.



                  Regards,
                  Nick Maclaren.

                  Comment

                  • Terry Reedy

                    #10
                    Re: Maths error


                    "Carsten Haese" <carsten@uniqsy s.comwrote in message
                    news:1168350028 .3722.3.camel@d ot.uniqsys.com. ..
                    | On Tue, 2007-01-09 at 11:38 +0000, Nick Maclaren wrote:
                    | As Dan Bishop says, probably not. The introduction to the decimal
                    | module makes exaggerated claims of accuracy, amounting to propaganda.
                    | It is numerically no better than binary, and has some advantages
                    | and some disadvantages.
                    |
                    | Please elaborate. Which exaggerated claims are made, and how is decimal
                    | no better than binary?

                    As to the latter question: calculating with decimals instead of binaries
                    eliminates conversion errors introduced when one has *exact* decimal
                    inputs, such as in financial calculations (which were the motivating use
                    case for the decimal module). But it does not eliminate errors inherent in
                    approximating reals with (a limited set of) ratrionals. Nor does it
                    eliminate errors inherent in approximation algorithms (such as using a
                    finite number of terms of an infinite series.

                    Terry Jan Reedy



                    Comment

                    • Simon Brunning

                      #11
                      Re: Maths error

                      On 1/9/07, Tim Peters <tim.one@comcas t.netwrote:
                      Well, just about any technical statement can be misleading if not qualified
                      to such an extent that the only people who can still understand it knew it
                      to begin with <0.8 wink>.
                      +1 QTOW

                      --
                      Cheers,
                      Simon B
                      simon@brunningo nline.net

                      Comment

                      • Robert Kern

                        #12
                        Re: Maths error

                        Bjoern Schliessmann wrote:
                        Nick Maclaren wrote:
                        >
                        >No, don't. That is about another matter entirely,
                        >
                        It isn't.
                        Actually it really is. That thread is about the difference between
                        str(some_float) and repr(some_float ) and why str(some_tuple) uses the repr() of
                        its elements.

                        --
                        Robert Kern

                        "I have come to believe that the whole world is an enigma, a harmless enigma
                        that is made terrible by our own mad attempt to interpret it as though it had
                        an underlying truth."
                        -- Umberto Eco

                        Comment

                        • Nick Maclaren

                          #13
                          Re: Maths error


                          In article <mailman.2493.1 168371116.32031 .python-list@python.org >,
                          Robert Kern <robert.kern@gm ail.comwrites:
                          |
                          |No, don't. That is about another matter entirely,
                          |
                          | It isn't.
                          |>
                          |Actually it really is. That thread is about the difference between
                          |str(some_float ) and repr(some_float ) and why str(some_tuple) uses the repr() of
                          |its elements.

                          Precisely. And it also applies to strings, which I had failed to
                          notice:
                          >>print ("1","2")
                          ('1', '2')
                          >>print "1", "2"
                          1 2


                          Regards,
                          Nick Maclaren.

                          Comment

                          • Tim Peters

                            #14
                            Re: Maths error

                            [Tim Peters]
                            ....
                            >|Well, just about any technical statement can be misleading if not
                            >|qualified to such an extent that the only people who can still
                            >|understand it knew it to begin with <0.8 wink>. The most dubious
                            >|statement here to my eyes is the intro's "exactness carries over
                            >|into arithmetic". It takes a world of additional words to explain
                            >|exactly what it is about the example given (0.1 + 0.1 + 0.1 - 0.3 =
                            >|0 exactly in decimal fp, but not in binary fp) that does, and does
                            >|not, generalize. Roughly, it does generalize to one important
                            >|real-life use-case: adding and subtracting any number of decimal
                            >|quantities delivers the exact decimal result, /provided/ that
                            >|precision is set high enough that no rounding occurs.
                            [Nick Maclaren]
                            Precisely. There is one other such statement, too: "Decimal numbers
                            can be represented exactly." What it MEANS is that numbers with a
                            short representation in decimal can be represented exactly in decimal,
                            which is tautologous, but many people READ it to say that numbers that
                            they are interested in can be represented exactly in decimal. Such as
                            pi, sqrt(2), 1/3 and so on ....
                            Huh. I don't read it that way. If it said "numbers can be ..." I
                            might, but reading that way seems to requires effort to overlook the
                            "decimal" in "decimal numbers can be ...".

                            [attribution lost]
                            >|>and how is decimal no better than binary?
                            >|Basically, they both lose info when rounding does occur. For
                            >|example,
                            Yes, but there are two ways in which binary is superior. Let's skip
                            the superior 'smoothness', as being too arcane an issue for this
                            group,
                            With 28 decimal digits used by default, few apps would care about this
                            anyway.
                            and deal with the other. In binary, calculating the mid-point
                            of two numbers (a very common operation) is guaranteed to be within
                            the range defined by those numbers, or to over/under-flow.
                            >
                            Neither (x+y)/2.0 nor (x/2.0+y/2.0) are necessarily within the range
                            (x,y) in decimal, even for the most respectable values of x and y.
                            This was a MAJOR "gotcha" in the days before binary became standard,
                            and will clearly return with decimal.
                            I view this as being an instance of "lose info when rounding does
                            occur". For example,
                            >>import decimal as d
                            >>s = d.Decimal("." + "9" * d.getcontext(). prec)
                            >>s
                            Decimal("0.9999 999999999999999 999999999")
                            >>(s+s)/2
                            Decimal("1.0000 000000000000000 00000000")
                            >>s/2 + s/2
                            Decimal("1.0000 000000000000000 00000000")

                            "The problems" there are due to rounding error:
                            >>s/2 # "the problem" in s/2+s/2 is that s/2 rounds up to exactly 1/2
                            Decimal("0.5000 000000000000000 000000000")
                            >>s+s # "the problem" in (s+s)/2 is that s+s rounds up to exactly 2
                            Decimal("2.0000 000000000000000 00000000")

                            It's always something ;-)

                            Comment

                            • Nick Maclaren

                              #15
                              Re: Maths error


                              In article <Xns98B3A00749D 6tim111one@216. 196.97.136>,
                              Tim Peters <tim.one@comcas t.netwrites:
                              |>
                              |Huh. I don't read it that way. If it said "numbers can be ..." I
                              |might, but reading that way seems to requires effort to overlook the
                              |"decimal" in "decimal numbers can be ...".

                              I wouldn't expect YOU to read it that way, but I can assure you from
                              experience that many people do. What it MEANS is "Numbers with a
                              short representation in decimal can be represented exactly in decimal
                              arithmetic", which is tautologous. What they READ it to mean is
                              "One advantage of representing numbers in decimal is that they can be
                              represented exactly", and they then assume that also applies to pi,
                              sqrt(2), 1/3 ....

                              The point is that the "decimal" could apply equally well to the external
                              or internal representation and, if you aren't fairly clued-up in this
                              area, it is easy to choose the wrong one.

                              ||>and how is decimal no better than binary?
                              |>
                              ||Basically, they both lose info when rounding does occur. For
                              ||example,
                              |>
                              | Yes, but there are two ways in which binary is superior. Let's skip
                              | the superior 'smoothness', as being too arcane an issue for this
                              | group,
                              |>
                              |With 28 decimal digits used by default, few apps would care about this
                              |anyway.

                              Were you in the computer arithmetic area during the "base wars" of the
                              1960s and 1970s that culminated with binary winning out? A lot of very
                              well-respected numerical analysts said that larger bases led to a
                              faster build-up of error (independent of the precision). My limited
                              investigations indicated that there was SOME truth in that, but it
                              wasn't a major matter; I never say the matter settled definitively.

                              | and deal with the other. In binary, calculating the mid-point
                              | of two numbers (a very common operation) is guaranteed to be within
                              | the range defined by those numbers, or to over/under-flow.
                              |
                              | Neither (x+y)/2.0 nor (x/2.0+y/2.0) are necessarily within the range
                              | (x,y) in decimal, even for the most respectable values of x and y.
                              | This was a MAJOR "gotcha" in the days before binary became standard,
                              | and will clearly return with decimal.
                              |>
                              |I view this as being an instance of "lose info when rounding does
                              |occur". For example,

                              No, absolutely NOT! This is an orthogonal matter, and is about the
                              loss of an important invariant when using any base above 2.

                              Back in the days when there were multiple bases, virtually every
                              programmer who wrote large numerical code got caught by it at least
                              once, and many got caught several times (it has multiple guises).
                              For example, take the following algorithm for binary chop:

                              while 1 :
                              c = (a+b)/2
                              if f(x) < y :
                              if c == b :
                              break
                              b = c
                              else :
                              if c == a :
                              break
                              a = c

                              That works in binary, but in no base above 2 (assuming that I haven't
                              made a stupid error writing it down). In THAT case, it is easy to fix
                              for decimal, but there are ways that it can show up that can be quite
                              tricky to fix.


                              Regards,
                              Nick Maclaren.

                              Comment

                              Working...