Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

decimal precision

by baxy77bax (Deacon)
on May 30, 2008 at 10:33 UTC ( [id://689177]=perlquestion: print w/replies, xml ) Need Help??

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

hi,

i need help with "rounding" the numbers. example:

use strict; use bignum; my $e = 0.00141; my $o =1; for(my $r=0; $r<=10; $r++){ $o *=$e; print "$o\n"; }
will produce :
0.00141 0.0000019881 0.000000002803221 0.00000000000395254161 0.0000000000000055730836701 0.000000000000000007858047974841 0.00000000000000000001107984764452581 0.0000000000000000000000156225851787813921 0.000000000000000000000000022027845102081762861 0.00000000000000000000000000003105926159393528563401 0.0000000000000000000000000000000437935588474487527439541
well the problem is that i would like to deal with only max 5 numbers after the last zero in the decimal number. meaning if the number is :  0.00000000000000000000000000003105926159393528563401 than i vould like to take the number
0.000000000000000000000000000031059
rounding the last digit (9 to 10 ->0 ; 31060) if the number after the 9 is 8 but if it is 1 or 2 like the example than 9 stays. and than deal with that number when calculating the next number in the iteration (last number in the list)

thanks

Replies are listed 'Best First'.
Re: decimal precision
by psini (Deacon) on May 30, 2008 at 10:56 UTC

    You can use

    $o=sprintf "%10.4e",$o; print "$o\n";
    to round up the value of $o at 5 significant digits. The result is:

    1.4100e-03 1.9881e-06 2.8032e-09 3.9525e-12 5.5730e-15 7.8579e-18 1.1080e-20 1.5623e-23 2.2028e-26 3.1059e-29 4.3793e-32

    If you don't like it to be in scientific notation you can add a $o+=0; between the two lines to force the value back to numeric:

    0.00141 0.0000019881 0.0000000028032 0.0000000000039525 0.000000000000005573 0.0000000000000000078579 0.00000000000000000001108 0.000000000000000000000015623 0.000000000000000000000000022028 0.000000000000000000000000000031059 0.000000000000000000000000000000043793

    Careful with that hash Eugene.

Re: decimal precision
by GrandFather (Saint) on May 30, 2008 at 11:12 UTC

    There are many ways to solve the problem, but here's a trick that may not leap straight to your finger tips:

    use warnings; use strict; use bignum; my $e = 0.00141; my $o =1; for (1 .. 10){ "@{[$o *= $e]}" =~ /(0\.0*\d{0,5})/; print "$1\n"; }

    Prints:

    0.00141 0.0000019881 0.0000000028032 0.0000000000039525 0.0000000000000055730 0.0000000000000000078580 0.000000000000000000011079 0.000000000000000000000015622 0.000000000000000000000000022027 0.000000000000000000000000000031059

    The @{[...]} trick is useful for interpolating the result of a chunk of code into a string. The rest should be pretty obvious, but note that if the regex doesn't match the print may generate some interesting results.

    Update: bah, forgot about the rounding. Oh well, the interpolation trick is still worth knowing even if it doesn't really help solve the OP's problem.


    Perl is environmentally friendly - it saves trees
      The @{[...]} trick is useful for interpolating the result of a chunk of code into a string.

      No doubt a nice trick... but in this particular case, the conversion to string would happen implicitly, i.e. you could also do

      ($o *= $e) =~ /(0\.0*\d{0,5})/;

      Yet another way would be to use bignum's accuracy option (which also does take care of the rounding)

      use bignum accuracy => 5; my $e = 0.00141; my $o = 1; for (1 .. 10) { $o *= $e; print "$o\n"; } __END__ 0.0014100 0.0000019881 0.0000000028032 0.0000000000039525 0.0000000000000055730 0.0000000000000000078579 0.000000000000000000011080 0.000000000000000000000015623 0.000000000000000000000000022028 0.000000000000000000000000000031059

      (see Math::BigInt and Math::BigFloat for details on rounding modes, accuracy, precision, etc.)

Re: decimal precision
by why_bird (Pilgrim) on May 30, 2008 at 15:08 UTC

    and than deal with that number when calculating the next number in the iteration (last number in the list)

    This suggests to me that you actually want to use the rounded number in the next line of your iteration. Is this intentional?

    A method that doesn't rely on interpreting the number in string context is as follows:

    use warnings; use strict; use bignum; sub trim { my $number=$_[0]; my $no_d_p=$_[1]; #number of decimal places die "$number is not a number" unless &isNumber($number); #check th +at you've got the right input die "$no_d_p is not an integer" unless int($no_d_p)==$no_d_p; my $power=0; for($power=0;$number<=(10**($no_d_p-1));$power++){ $number*=10; } $number=int($number); $number/=(10**$power); return($number); } sub isNumber { my $number=$_[0]; if ($number !~ /^\-?\d+(?:\.\d+)?(?:[Ee][+-]?\d{1,3})?$/){ return 0; } else { return 1; } } my $e = 0.00141; my $o =1; for(my $r=0; $r<=10; $r++){ $o *=$e; $o=&trim($o,5); print "$o\n"; } exit 0;
    prints:
    0.00141 0.0000019881 0.0000000028032 0.0000000000039525 0.000000000000005573 0.0000000000000000078579 0.000000000000000000011079 0.000000000000000000000015621 0.000000000000000000000000022025 0.000000000000000000000000000031055 0.000000000000000000000000000000043787

    This obviously introduces rounding errors. is that what you want or have I mis-interpreted the question?

    ........
    Those are my principles. If you don't like them I have others.
    -- Groucho Marx
    .......

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://689177]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-19 22:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found