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

hey,,i'm sorta new to perl and this site. I was wondering how I can round a number with only one decimal place. So I want to round the number 28.5 to 29. Can anyone show me a link on where to find how I can do this best? Thanks!

Replies are listed 'Best First'.
Re: Rounding a number?
by Corion (Patriarch) on Jun 09, 2005 at 08:39 UTC

    This is a FAQ.

    You can find the Perl FAQ at perlfaq4 (alternative), but you can also search it locally by entering perldoc -q question at the command prompt, in your example:

    perldoc -q round

    Of course, your question makes me want to start off on the rant about which train of thought makes people ask this question without showing what they've tried already, but this great rant has already been made by people much better at Perl and ranting than I will ever be.

    Update:

Re: Rounding a number?
by TedPride (Priest) on Jun 09, 2005 at 08:53 UTC
    $num = int($num + .5);
Re: Rounding a number?
by tlm (Prior) on Jun 09, 2005 at 12:03 UTC

    My first thought when I saw this question was sprintf, which is Perl's standard approach to rounding, but then I saw ghenry's comment and realized that sprintf doesn't do what the OP specifically asked for, because for numbers exactly at the halfway point between two integers, perl always rounds towards the even number. So, as ghenry notes, sprintf '%.f', 28.5 yields 28, not the 29 that the OP requested.

    Therefore, I think that Ted Pride's solution is the one that best meets the OP's requirement, since it will always round up at the halfway points.

    But keep in mind that with this solution, a negative halfway-point number such as -28.5 gets rounded to -28, not -29.

    I'm not sure what the best solution would be if what one wants is that halfway-point numbers get rounded "away from zero" (as opposed to "up"), so that -28.5 gets rounded to -29. One awkward solution is to mess around with absolute values and signs, like this:

    sub round { my $n = shift; my $abs = abs( $n ); return 0 if $abs < 0.5; my $sign = $n/$abs; return int( $abs + 0.5 ) * ( $n/$abs ); } print round( $_ ), $/ for qw( -1.5 -0.5 0 0.5 1.5 ); __END__ -2 -1 0 1 2
    But, eeewwww! I hope there's a more elegant approach...

    Update: Replaced the test for the 0 condition, to avoid divisions by very small numbers. But this modest improvement is moot, since Roy Johnson's solution++ is indeed far more palatable. I had not realized that one can get a nice sign operator out of <=>. That alone takes care of my Perl learning quota for today...

    the lowliest monk

      You might find this a little more palatable:
      sub round { my $n = shift; return $n unless $n; my $sign = $n <=> 0; return int( $n + $sign * 0.5); }

      Caution: Contents may have been coded under pressure.
      My first thought when I saw this question was sprintf, which is Perl's standard approach to rounding, but then I saw ghenry's comment and realized that sprintf doesn't do what the OP specifically asked for, because for numbers exactly at the halfway point between two integers, perl always rounds towards the even number.

      Due to the "miracles" of IEEE floating point computation and rounding, we also have the following craziness:

      $ perl -e'for( $d=0; $d<1; $d+=0.05 ){ printf "%.2f ~ %.1f\n", $d, $d; + }' 0.00 ~ 0.0 0.05 ~ 0.1 0.10 ~ 0.1 0.15 ~ 0.2 0.20 ~ 0.2 0.25 ~ 0.2 0.30 ~ 0.3 0.35 ~ 0.3 0.40 ~ 0.4 0.45 ~ 0.4 0.50 ~ 0.5 0.55 ~ 0.5 0.60 ~ 0.6 0.65 ~ 0.7 0.70 ~ 0.7 0.75 ~ 0.8 0.80 ~ 0.8 0.85 ~ 0.9 0.90 ~ 0.9 0.95 ~ 1.0

      (Notice the 3 0.2s and only 1 0.6. At least the output from an equivalent C program is identical.) But this should be expected with floating point ...

Re: Rounding a number?
by davidrw (Prior) on Jun 09, 2005 at 12:35 UTC
Re: Rounding a number?
by PetaMem (Priest) on Jun 09, 2005 at 09:00 UTC

    See the Perl Cookbook "2.3. Rounding Floating-Point Numbers".

    Use the Perl function sprintf, or printf if you're just trying to produce output:

    $rounded = sprintf("%FORMATf", $unrounded);

    Bye
     PetaMem
        All Perl:   MT, NLP, NLU

Re: Rounding a number?
by ghenry (Vicar) on Jun 09, 2005 at 08:48 UTC

    Updated: Provided working code, which doesn't work for 28.5, as it rounds to 28. Please ignore my solution.

    See sprintf and Does Perl have a round() function? What about ceil() and floor()? Trig functions?, eg:

    use warnings; use strict; my $number = 28.5555; # round number to no decimal places. my $rounded = sprintf("%.0f", $number); print "$rounded\n";

    HTH.

    Walking the road to enlightenment... I found a penguin and a camel on the way.....
    Fancy a yourname@perl.me.uk? Just ask!!!
A reply falls below the community's threshold of quality. You may see it by logging in.