Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Perl Misc (http://www.velocityreviews.com/forums/f67-perl-misc.html)
-   -   Arbitrary decimal places in addition (http://www.velocityreviews.com/forums/t890430-arbitrary-decimal-places-in-addition.html)

Matthew Keene 01-27-2005 01:21 AM

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 ?

Chris Mattern 01-27-2005 02:03 AM

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?"

Jürgen Exner 01-27-2005 02:47 AM

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



Bill Smith 01-27-2005 05:29 AM

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.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57