Scientific notation - no rounding errors?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Joe Attardi

    Scientific notation - no rounding errors?

    Hi all,

    Math is not my strongest area so forgive me if I use some of the wrong
    terminology.
    It seems that scientific notation is immune to rounding errors. For
    example:

    (4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
    4.98e2 + 5.51 // returns 503.51, correct!

    Why are scientific notation numbers not affected? And if this is true,
    does this mean that scientific notation would be safe to use in a
    floating-point addition function?

    For example, 4.98 + 0.2, which comes out to 5.1800000000000 01
    (incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
    5.18 (correct!)

    Any insight would be appreciated...

    --
    Joe

  • Evertjan.

    #2
    Re: Scientific notation - no rounding errors?

    Joe Attardi wrote on 16 mei 2006 in comp.lang.javas cript:
    [color=blue]
    > Math is not my strongest area so forgive me if I use some of the wrong
    > terminology.
    > It seems that scientific notation is immune to rounding errors. For
    > example:
    >
    > (4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
    > 4.98e2 + 5.51 // returns 503.51, correct!
    >
    > Why are scientific notation numbers not affected?[/color]

    Wrong, it is untrue.
    [color=blue]
    > And if this is true,
    > does this mean that scientific notation would be safe to use in a
    > floating-point addition function?[/color]

    Unanswerable.
    [color=blue]
    > For example, 4.98 + 0.2, which comes out to 5.1800000000000 01
    > (incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
    > 5.18 (correct!)[/color]

    Only a single negative example can prove a point [to be incorrect],
    while any finite number of positive examples is not enough for
    correctness.

    <http://en.wikipedia.or g/wiki/Reductio_ad_abs urdum>
    [color=blue]
    > Any insight would be appreciated...[/color]

    Javascript arythmetic and storage use binary [=base 2] numbers.
    All fraction numbers or results that are not exact floating point
    binaries could introduce rounding errors, seen from a decimal world, or
    through overflow of the mantissa.

    So decimal 0.5 and 5e-1 are both exactly binary 0.1 and will make no
    problems. 0.2 or 2e-1 [1/5] already gives me the creeps binary.

    --
    Evertjan.
    The Netherlands.
    (Please change the x'es to dots in my emailaddress)

    Comment

    • Joe Attardi

      #3
      Re: Scientific notation - no rounding errors?

      Evertjan. wrote:[color=blue][color=green]
      > > (4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
      > > 4.98e2 + 5.51 // returns 503.51, correct!
      > > Why are scientific notation numbers not affected?[/color]
      >
      > Wrong, it is untrue.[/color]
      If it is untrue, then why do the two examples come out with different
      values?
      [color=blue]
      > Only a single negative example can prove a point [to be incorrect],
      > while any finite number of positive examples is not enough for
      > correctness.[/color]
      I realize that. I'm not trying to do a proof here, I'm just asking for
      advice.
      [color=blue]
      > Javascript arythmetic and storage use binary [=base 2] numbers.
      > All fraction numbers or results that are not exact floating point
      > binaries could introduce rounding errors, seen from a decimal world, or
      > through overflow of the mantissa.[/color]
      So what can I do to properly show the sum of an addition?
      The point of trying to use the scientific notation is to do what I
      think is called scaled integer arithmetic? That is, 4.98 + 0.2 becomes
      498 + 20, then the addition is integer addition, then the result is
      divided back down for the correct result.

      If using multiplication and division to move the decimal point won't
      work, due to the floating point inaccuracies, what about (I know this
      sounds messy) converting them to strings, counting the decimal places
      in the string, removing the decimal point from the string, convert back
      to numbers, perform the calculations, and merely insert a decimal point
      in the string of the result?

      I know that sounds inefficient but it at least would get a proper
      result, I think.

      Comment

      • Rob

        #4
        Re: Scientific notation - no rounding errors?

        This problem is not limited to JavaSript. You may want to bone up on
        the subject in a general cs book. There are a number of solutions to
        handle rounding errors and I'm sure I don't know half of them. Your
        solution of scaling the number, truncating to an integer and then
        scaling back is one. The truncation hides the round off error.

        The best solution is to format the numbers to show only the number of
        significant digits your application requires. This hides the rounding
        errors. It's up to you to design your application so that these errors
        do not accumulate until a noticeable error occurs. If you use a
        spreadsheet, these same factors apply. They just don't show you all the
        digits by default. That's how the errors are hidden in a spreadsheet.

        Rob:-]

        Comment

        • cwdjrxyz

          #5
          Re: Scientific notation - no rounding errors?


          Joe Attardi wrote:[color=blue]
          > Hi all,
          >
          > Math is not my strongest area so forgive me if I use some of the wrong
          > terminology.
          > It seems that scientific notation is immune to rounding errors. For
          > example:
          >
          > (4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
          > 4.98e2 + 5.51 // returns 503.51, correct!
          >
          > Why are scientific notation numbers not affected? And if this is true,
          > does this mean that scientific notation would be safe to use in a
          > floating-point addition function?
          >
          > For example, 4.98 + 0.2, which comes out to 5.1800000000000 01
          > (incorrect!), would become (498e2 + 0.2e2) / 1e2, which comes out to
          > 5.18 (correct!)
          >
          > Any insight would be appreciated...[/color]

          Modern computers use number systems based on 2 or powers thereof such
          as 2(binary), 4, 8(octal), 16(hex), 32, 64, 128 and so on. Most western
          math is on a base 10 system. Anytime you convert from one number system
          to another, there are going to be some errors introduced, as non-exact
          numbers result in some cases. If you use decimals and allow division,
          this ensures some numbers can not be represented exactly in some
          systems. Consider that in the ordinary base 10 number system, division
          of 1 by 3 gives a decimal number .33333 to infinity that can not be
          written exactly.

          The reason for the scientific number system is that some huge and very
          small numbers are often used, and you do not want to have to write a
          lot of leading or trailing zeros to do calculations. Some scientifc
          calculations, if not very carefully programmed, will cause underflows
          or overflows even if the computer can handle exp(100).

          The 'funny" roundoffs have been with computing for well over 50 years
          since digital computers based on a binary system were introduced, and
          methods for handling this have been around just as long. People that
          did money calculations soon started using cents rather than dollars in
          the US so that fractions were avoided in additions and subtractions so
          that "funny" numbers such as $1.00000001 would not disturb the bean
          counters. In fact IBM had two different programs systems that were
          widely used. Fortran was used for scientific calculations, and Cobal
          was used for money calculations.

          Comment

          • Rob

            #6
            Re: Scientific notation - no rounding errors?

            Here's a nice set of JavaScript techniques to deal with the problem:



            Or for a more rigorous treatment of the subject:



            Comment

            • Rob

              #7
              Re: Scientific notation - no rounding errors?

              var num = 10;
              var result = num.toFixed(2); // result will equal 10.00

              num = 930.9805;
              result = num.toFixed(3); // result will equal 930.981

              num = 500.2349;
              result = num.toPrecision (4); // result will equal 500.2

              num = 5000.2349;
              result = num.toPrecision (4); // result will equal 5000

              num = 555.55;
              result = num.toPrecision (2); // result will equal 5.6e+2

              Comment

              • Joe Attardi

                #8
                Re: Scientific notation - no rounding errors?

                Rob wrote:[color=blue]
                > The best solution is to format the numbers to show only the number of
                > significant digits your application requires.[/color]

                I basically need to compare a maximum to a computed total. The maximum
                isn't known until runtime. So, to get the number of decimal places I
                need, I could just count the number of decimal places in the maximum
                and round the computed total to that many places?

                Comment

                • Lasse Reichstein Nielsen

                  #9
                  Re: Scientific notation - no rounding errors?

                  "Joe Attardi" <jattardi@gmail .com> writes:
                  [color=blue]
                  > Evertjan. wrote:[color=green][color=darkred]
                  >> > (4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
                  >> > 4.98e2 + 5.51 // returns 503.51, correct!
                  >> > Why are scientific notation numbers not affected?[/color]
                  >>
                  >> Wrong, it is untrue.[/color]
                  > If it is untrue, then why do the two examples come out with different
                  > values?[/color]

                  Because 498 (aka. 4.98e2) can be represented exactly in the
                  representation used by Javascript's number type, but 4.98 cannot.

                  When you write 498 or 4.98e2 you get exactly that value.

                  The literal "4.98" does not give exactly the value 4.98, but rather
                  the representable value that is closest to that number. There is a
                  difference. When you then multiply by 100, the difference is also
                  multiplied, making it even more visible.
                  [color=blue]
                  > So what can I do to properly show the sum of an addition?[/color]

                  More importantly, how can you ensure that each operand of the
                  addition is exactly the number you expect? Generally, you can't.
                  [color=blue]
                  > The point of trying to use the scientific notation is to do what I
                  > think is called scaled integer arithmetic? That is, 4.98 + 0.2 becomes
                  > 498 + 20, then the addition is integer addition, then the result is
                  > divided back down for the correct result.[/color]

                  I don't know the name, but the approach is sound (as long as you
                  don't get results so big that they loose precission, i.e., something
                  that cannot be represented with 53 bits preission).
                  [color=blue]
                  > If using multiplication and division to move the decimal point won't
                  > work, due to the floating point inaccuracies, what about (I know this
                  > sounds messy) converting them to strings, counting the decimal places
                  > in the string, removing the decimal point from the string, convert back
                  > to numbers, perform the calculations, and merely insert a decimal point
                  > in the string of the result?[/color]

                  Workable. You could also start out with two integer literals, one
                  for the number without the decimal point and one the position of
                  the point. Harder to read, but saves parsing the string.

                  Or you could create your own decimal number representation. Something
                  like:
                  ---
                  function Dec(n,mag) {
                  this.n = Math.floor(n);
                  this.mag = Math.floor(mag) ;
                  }
                  Dec.prototype.a dd = function add(dec) {
                  if (this.mag < dec.mag) {
                  return dec.add(this);
                  }
                  var diff = this.mag - dec.mag;
                  return new Dec(this.n + Math.pow(10,dif f) * dec.n, this.mag);
                  };
                  Dec.prototype.m ult = function mult(dec) {
                  return new Dec(this.n * dec.n, this.mag + dec.mag);
                  };
                  Dec.prototype.t oString = function toString() {
                  var n = this.n;
                  var mag = this.mag;
                  var res = [];
                  var sign = "";
                  if (n < 0) {
                  n = -n;
                  sign = "-";
                  }
                  while(mag > 0) {
                  res.push("0");
                  mag--;
                  }
                  while(n > 0) {
                  res.push(String (n%10));
                  n = Math.floor(n / 10);
                  mag++;
                  if (mag == 0) {
                  res.push(".");
                  }
                  }
                  while(mag < 0) {
                  res.push("0");
                  mag ++;
                  if (mag == 0) {
                  res.push(".");
                  }
                  }
                  res.push(sign);
                  return res.reverse().j oin("");
                  };

                  var d1 = new Dec(5); // 5.0
                  var d2 = new Dec(5,-1); // 0.5
                  var d3 = new Dec(5,1); //50.0
                  alert([d1.mult(d2),
                  d1.mult(d3),
                  d3.mult(d3),
                  d2.mult(d2)]); // 2.5,250,2500,.2 5

                  ---
                  Div and mod are the harder ones. You must still beware of overflow.

                  Good luck
                  /L
                  --
                  Lasse Reichstein Nielsen - lrn@hotpop.com
                  DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
                  'Faith without judgement merely degrades the spirit divine.'

                  Comment

                  • Dr John Stockton

                    #10
                    Re: Scientific notation - no rounding errors?

                    JRS: In article <1147799816.651 648.145480@j33g 2000cwa.googleg roups.com>
                    , dated Tue, 16 May 2006 10:16:56 remote, seen in
                    news:comp.lang. javascript, Joe Attardi <jattardi@gmail .com> posted :
                    [color=blue]
                    >Math is not my strongest area so forgive me if I use some of the wrong
                    >terminology.
                    >It seems that scientific notation is immune to rounding errors. For
                    >example:
                    >
                    >(4.98 * 100) + 5.51 // returns 503.51000000000 005, rounding error!
                    >4.98e2 + 5.51 // returns 503.51, correct![/color]

                    But that is a simpler calculation, one operation instead of two.
                    4.98*100 does not show 498.

                    [color=blue]
                    >Why are scientific notation numbers not affected? And if this is true,
                    >does this mean that scientific notation would be safe to use in a
                    >floating-point addition function?
                    >
                    >For example, 4.98 + 0.2, which comes out to 5.1800000000000 01
                    >(incorrect!) , would become (498e2 + 0.2e2) / 1e2, which comes out to
                    >5.18 (correct!)[/color]

                    It does not come out to 5.18, since a Number, being an IEEE Double,
                    cannot represent 5.18 exactly. However, conversion to String, for
                    output, would give something so close to 5.18 that 5.18 would be shown.

                    Now 5, being an integer no bigger than 2^53, is held exactly;
                    and 5.18-5 gives 0.1799999999999 9971
                    and (5.18-5)*100-18 gives -2.8421709430404 01e-14

                    A value exact in cents but handled as euros.cents will generally be
                    represented inexactly, and arithmetic will generally introduce further
                    error. But if the work is done in cents, it will be done without error.

                    I think an exact number of cents divided by 100 and converted to String
                    will be shown as you would wish, except for suppression of trailing
                    zeroes; it would be better to convert the integer to String and insert
                    the decimal point by character manipulation (e.g. RegExp .replace).

                    Note that multiplication by 0.01 gives inexact results, since 0.01
                    cannot be held exactly -
                    try for (J=0; J<1111; J++) document.writel n(J / 100, '<br>')
                    and for (J=0; J<1111; J++) document.writel n(J * 0.01, '<br>')

                    [color=blue]
                    >Any insight would be appreciated...[/color]

                    Read the newsgroup FAQ, sections 4.7, 4.6; read <URL:http://www.merlyn.
                    demon.co.uk/js-maths.htm> and follow links therein.

                    --
                    © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
                    <URL:http://www.jibbering.c om/faq/> JL/RC: FAQ of news:comp.lang. javascript
                    <URL:http://www.merlyn.demo n.co.uk/js-index.htm> jscr maths, dates, sources.
                    <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

                    Comment

                    Working...