![]() |
Arbitrary decimal places in addition
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 ? |
Re: Arbitrary decimal places in addition
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?" |
Re: Arbitrary decimal places in addition
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 |
Re: Arbitrary decimal places in addition
"Matthew Keene" <dfg778@yahoo.com.au> wrote in message news:bb27253c.0501261721.214b3b52@posting.google.c om... --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 |
| All times are GMT. The time now is 07:45 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.