Arbitrary decimal places in addition

Discussion in 'Perl Misc' started by Matthew Keene, Jan 27, 2005.

  1. I'm sure this question has been asked before, but I couldn't find
    anything that really satisfactorily explained it, so please excuse me
    if I'm going over old ground.

    We have a program which totals decimal numbers in a file. The code in
    the program looks something like this (I've added the print statements
    to see what's going on):

    use English ;

    open (FILE,"DMD_WKG_FCT.TXT") or die "Couldn't open file" ;
    while (defined($line = <FILE>)) {
    chomp $line ;
    @fields = split(/\t/,$line) ;
    next if $INPUT_LINE_NUMBER == 1 ;
    print "Input field = $fields[11] $sum\n" ;
    }

    print $sum ;

    and the output that this produces looks like this (I've trimmed the
    output to show the sections which illustrate the behaviour I'm talking
    about)

    Input field = 2.5237 Running total = 9864.4567
    Input field = 0.8571 Running total = 9865.3138
    Input field = 0.8571 Running total = 9866.1709
    Input field = 15.6639 Running total = 9881.8348
    Input field = 16.6392 Running total = 9898.47399999999
    Input field = 6.6188 Running total = 9905.09279999999
    Input field = 19.9114 Running total = 9925.0042
    Input field = 0.0000 Running total = 9925.0042
    Input field = 0.0000 Running total = 9925.0042
    Input field = 0.0000 Running total = 9925.0042
    Input field = 0.0000 Running total = 9925.0042
    Input field = 0.0001 Running total = 9925.0043
    Input field = 0.0001 Running total = 9925.00439999999
    Input field = 0.0001 Running total = 9925.00449999999
    Input field = 0.0001 Running total = 9925.00459999999
    Input field = 4.0370 Running total = 9929.04159999999

    Where did the extra decimal places come from ?

    Now, we could probably solve this by rounding all numbers to 4 decimal
    places, but the problem is that this is a utility program which is
    meant to be able to handle an arbitrary number of decimal places, so
    we wouldn't necessary know how many decimal places to round to (I
    guess we could find the greatest number of decimal places in the input
    and round to that, but this seems to be getting a bit silly).

    Can anybody explain this behaviour and the best way to get around it ?
    Matthew Keene, Jan 27, 2005
    #1
    1. Advertising

  2. Matthew Keene wrote:

    > I'm sure this question has been asked before, but I couldn't find
    > anything that really satisfactorily explained it, so please excuse me
    > if I'm going over old ground.
    >
    > We have a program which totals decimal numbers in a file. The code in
    > the program looks something like this (I've added the print statements
    > to see what's going on):
    >
    > use English ;
    >
    > open (FILE,"DMD_WKG_FCT.TXT") or die "Couldn't open file" ;
    > while (defined($line = <FILE>)) {
    > chomp $line ;
    > @fields = split(/\t/,$line) ;
    > next if $INPUT_LINE_NUMBER == 1 ;
    > print "Input field = $fields[11] $sum\n" ;
    > }
    >
    > print $sum ;
    >
    > and the output that this produces looks like this (I've trimmed the
    > output to show the sections which illustrate the behaviour I'm talking
    > about)
    >
    > Input field = 2.5237 Running total = 9864.4567
    > Input field = 0.8571 Running total = 9865.3138
    > Input field = 0.8571 Running total = 9866.1709
    > Input field = 15.6639 Running total = 9881.8348
    > Input field = 16.6392 Running total = 9898.47399999999
    > Input field = 6.6188 Running total = 9905.09279999999
    > Input field = 19.9114 Running total = 9925.0042
    > Input field = 0.0000 Running total = 9925.0042
    > Input field = 0.0000 Running total = 9925.0042
    > Input field = 0.0000 Running total = 9925.0042
    > Input field = 0.0000 Running total = 9925.0042
    > Input field = 0.0001 Running total = 9925.0043
    > Input field = 0.0001 Running total = 9925.00439999999
    > Input field = 0.0001 Running total = 9925.00449999999
    > Input field = 0.0001 Running total = 9925.00459999999
    > Input field = 4.0370 Running total = 9929.04159999999
    >
    > Where did the extra decimal places come from ?


    Rounding errors. The computer is not doing the arithmetic in decimal,
    and so cannot always represent your decimal fractions with complete
    accuracy. It must often round when converting your input. In particular,
    0.0001 is a non-terminating decimal in binary floating point.
    Sometimes the rounding errors show up in your output. Among other things,
    this results in the First Commandment of Floating Point: "Thou shalt
    not compare two floats for equality," since you can't count on the
    rounding errors having made them unequal when they shouldn't be.
    >
    > Now, we could probably solve this by rounding all numbers to 4 decimal
    > places, but the problem is that this is a utility program which is
    > meant to be able to handle an arbitrary number of decimal places, so
    > we wouldn't necessary know how many decimal places to round to (I
    > guess we could find the greatest number of decimal places in the input
    > and round to that, but this seems to be getting a bit silly).
    >
    > Can anybody explain this behaviour and the best way to get around it ?


    Basically, if you must have arbitrary precision, you're going to have to
    go out and get it; look at the Math::BigFloat package that's standard.
    Note that you *still* have to know what precision and accuracy you want.

    --
    Christopher Mattern

    "Which one you figure tracked us?"
    "The ugly one, sir."
    "...Could you be more specific?"
    Chris Mattern, Jan 27, 2005
    #2
    1. Advertising

  3. Matthew Keene wrote:
    [...]
    > Input field = 0.0001 Running total = 9925.00449999999
    > Where did the extra decimal places come from ?

    [...]

    Your Question is Asked Frequently, please see "perldoc -q 9999" for the
    answer.

    jue
    Jürgen Exner, Jan 27, 2005
    #3
  4. Matthew Keene

    Bill Smith Guest

    "Matthew Keene" <> wrote in message
    news:...
    --snip
    > guess we could find the greatest number of decimal places in the input
    > and round to that, but this seems to be getting a bit silly).
    >


    If you want the input format to control the output format, yes, you do
    have to do it explicitly.

    This is not a limitation of perl, but rather of binary floating point
    arithmetic. Nearly all computers do arithmetic with some variation of
    this. All general purpose languages such as perl use the computer's
    arithmethic instructions.

    Bill
    Bill Smith, Jan 27, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eoin Mcloughlin

    Decimal places and huge fractions.

    Eoin Mcloughlin, Feb 11, 2004, in forum: Perl
    Replies:
    5
    Views:
    1,612
    Eoin Mcloughlin
    Feb 13, 2004
  2. Curt_C [MVP]

    Re: beginner: prob with decimal places

    Curt_C [MVP], May 18, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    335
    Curt_C [MVP]
    May 18, 2004
  3. Curt_C [MVP]

    Re: beginner: prob with decimal places

    Curt_C [MVP], May 18, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    543
    Curt_C [MVP]
    May 18, 2004
  4. Harry

    Remove Decimal Places

    Harry, Jun 3, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    8,945
    VB Programmer
    Jun 3, 2004
  5. Honestmath
    Replies:
    5
    Views:
    554
    Honestmath
    Dec 13, 2004
Loading...

Share This Page