http://qs321.pair.com?node_id=17681

daemonchild has asked for the wisdom of the Perl Monks concerning the following question:

hello all

i have written a script that does some price calculations based on input thru drop down menus (CGI). It all works, but I am running into problems maintaining the correct number of significant digits in calculations.

for example, trailing zeros are just obliterated, eg

2*120.00 = 240

and decimal calculations often end up with 4 or 5 trailing decimals. is there an easy way to specify 2 trailing decimal places? or am i relegated to the following ugly hacks ...

if ($price !~ /\./) { $price .= ".00"; } else { $price =~ s/(\d*?\.\d\d).*/$1/; }
much thanks,

--steve

Replies are listed 'Best First'.
Re: significant digits in computations
by btrott (Parson) on Jun 12, 2000 at 11:28 UTC
Re: significant digits in computations
by plaid (Chaplain) on Jun 12, 2000 at 11:30 UTC
      d'oh!

      i guess i didn't look hard enough for an answer!

      thanks all for the help .. that fixed it

      -- steve

Re: significant digits in computations
by Perlmage (Acolyte) on Jun 12, 2000 at 22:35 UTC

    Never underestimate the power of CPAN:

      Math::SigFigs - do math with correct handling of significant figures
    
      In many scientific applications, it is often useful to be
      able to format numbers with a given number of significant
      figures, or to do math in such a way as to maintain the
      correct number of significant figures.  The rules for
      significant figures are too complicated to be handled
      solely using the sprintf function (unless you happen to be
      Randal Schwartz :-).
    
      I just rolled my own significant digits subroutines and felt like I should look it up to see what other people have done before I start incorporating it in any apps I roll out - in case anyone handled it better. I took a look at Math::SigFigs, and I'm not sure I agree with the way some of the numbers are handled. First, I've never seen a number with a trailing decimal point to suggest that any trailing zeroes to the left of it are significant. Without that decimal point, the module assumes that all trailing zeros in whole numbers are not significant, but while I understand the intent here, I'd be wary of the output. 0 is a digit just like any other and does not necessarily convey significance when the number ends with some number of zeros. You could have any number of trailing zeros and any fraction of them could be significant. Also, the module does not handle exponents. I wrote my code to extract the number from the left of the exponent and make a recursive call with it, tacking the exponent back on when it comes back. This module just returns undef. That said, this module appears written more efficiently than my attempt - just be aware of the caveats.
      This is just what I was talking about in my earlier post. I only wish it had a better (object oriented) interface that could be used transparently in arithmetic. Doing a complicated formula using Math::SigFigs seems like a lot of trouble.
Re: significant digits in computations
by lhoward (Vicar) on Jun 12, 2000 at 16:19 UTC
    This is slightly off-topic since the original poster was asking about fixed-point arithmetic, and not really significant digits, but....

    It would be cool to have a perl library that would automatically apply the scientific "number of significant digits" rules.

    my $n1=new Number::Scientific(5500,3); #5500 w/ 3 significatn digits my $n2=new Number::Scientific(3.141592,7) # pi w/ 7 siginificant digit +s my $n3=$n1*$n2; my $n4=$n2/$n1; my $n5=$n1+$n2; print "$n3 $n4 $n5\n";
    would output 17300 0.000571 5500. Unfortunately I don't think any such beast exists.

      What about Math::BigFloat? It's in the standard distribution since about 5.002, I think. Or do you mean something to track Significant Digits and make the results of their calculations return only the sigdigs?
        What I am talking about is something that would track (and apply) significant digits internally. I could multiply a number with 2 significant digits by a number with 3 significant digits and when I went to display the results it would know that there were 2 significant digits and display apropriately without having to manually keep track of significant digits or decimal places myself.