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

Say I have: $pete=20.875 then I have $rooker = sprintf ("%.2f", $pete); Thus, shouldn't $rooker be equal to 20.88 ???? Yet, when I do it, it doesn't work. Do I have something wrong? Thanks, Pete PS: In the end, all I need to do is round $pete to 20.88... any ideas would be a *huge* help.
  • Comment on A simple rounding question, but can't get it!

Replies are listed 'Best First'.
Re: A simple rounding question, but can't get it!
by Masem (Monsignor) on Feb 01, 2002 at 04:01 UTC
    What is probably happening is that as a float, 20.875 is being represented as "20.8749999999...", which, when rounded to 2 decimal places, is being represented as 20.87. (Though, theorhetically, 0.875 should be able to be represented exactly by decimal fractions, but there's still some floating point math).

    A general way to round to some place can be done by the following:

    my $rounded = int ( $value / ( 10**$round ) + 0.5 ) * ( 10**$round );
    where $round is the digit that you want to round to, 0 being the 1's place, 1 the tens, and -1 the tenths place. (and so forth). You'll want to do something with $round = -2 in your case here.

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

Re: A simple rounding question, but can't get it!
by Zaxo (Archbishop) on Feb 01, 2002 at 06:16 UTC

    In cb, you indicated that the general problem is to do a Banker's Round, where /\d5/ is rounded to the even digit. I think you want to work with the string representation of the number for this, so that machine numbers don't interfere with the rules.

    # handle 5 in the thousandth's place with nothing or zeros following $pete =~ s/( # substitute, start capture $1 \d* # none or more digits \. # a decimal point \d # tenths digit (\d) # capture hundredths digit as $2 ) # end capture $1 50*$ # digit 5 followed by none or more 0's to the end /1&$2 ? $1+.01 : $1/xe; # then do as you had $rooker = sprintf "%.2f", $pete;
    By handling the special case as a string before the numeric round, we avoid binary-meets-decimal conflicts.

    After Compline,
    Zaxo

Re: A simple rounding question, but can't get it!
by shotgunefx (Parson) on Feb 01, 2002 at 03:53 UTC
    The code you post, appears correct. Maybe you should post the code snippet itself. Most likely something else going on.
    You also neglect to say what it does produce.
    perl -e 'my $e="20.875"; my $r=sprintf("%.2f",$e);print $r'
    prints 20.88

    -Lee

    "To be civilized is to deny one's nature."
      if ($coupon_style eq "A" && $subtotal-$acoup_not_allowed_for_this_part + >= $must_spend) { $take_off_this_much = ($coupon_amount/100) * ($subtotal-$acoup_n +ot_allowed_for_this_part); $a_take_off_this_much = sprintf ("%.2f", $take_off_this_much); $b_take_off_this_much = &display_price($a_take_off_this_much); $coup_work= sprintf("%.2f", $take_off_this_much); $rooker = sprintf ("%.2f", $take_off_this_much); $a1_num_grand_total = sprintf ("%.2f", $num_grand_total); $num_grand_total = $a1_num_grand_total; $fiddler = ($num_grand_total - $coup_work); $a_fiddler = &format_price($fiddler); $b_fiddler = &display_price($a_fiddler);
      $a_take_off_this_much is what we are looking at here, say the actual number is 1.085, it returns 1.08 (bad).

      I'm not sure I understand the second reply... (sorry, I'm quite new at this).

      Thanks again,

      Pete

      Edit by tye

        Need to use <code></code> tags around your code.

        -Lee

        "To be civilized is to deny one's nature."