go ahead... be a heretic PerlMonks

### Best way to round a number.

 on Oct 24, 2012 at 23:07 UTC Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I need to round a number to its nearest 5 I would say, like; if I have 33 it should give me 30, if its 3 I should get 5, if its 36 I should get 40, if its 5 it should be 5, if its 6 it should be 10 and so on. This is what I have, see the code below. Is there a better way of doing this?
```use strict;
use warnings;
use POSIX qw(ceil);
use POSIX qw(floor);

my \$num = 11;
\$num =~ m/\d*(\d{1})/;

my \$check = \$1;

if(\$check < 5) {

\$num = ceil(\$num/5)*5;

}else {

\$num = floor(\$num/5)*5;
}

print "\n \$num \n\n";

Thanks for looking!

Replies are listed 'Best First'.
Re: Best way to round a number.
by BrowserUk (Pope) on Oct 25, 2012 at 01:01 UTC

If you actually want "the nearest multiple of 5", then:

```sub roundToNearest5{
5 * int( ( \$_[0] + ( 2 * ( \$_[0] <=> 0 ) ) ) / 5 );
}

print "\$_: ", roundToNearest5( \$_ ) for -18..+18;;
-18:  -20
-17:  -15
-16:  -15
-15:  -15
-14:  -15
-13:  -15
-12:  -10
-11:  -10
-10:  -10
-9:  -10
-8:  -10
-7:  -5
-6:  -5
-5:  -5
-4:  -5
-3:  -5
-2:  0
-1:  0
0:  0
1:  0
2:  0
3:  5
4:  5
5:  5
6:  5
7:  5
8:  10
9:  10
10:  10
11:  10
12:  10
13:  15
14:  15
15:  15
16:  15
17:  15
18:  20

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
codecode
Re: Best way to round a number.
by Anonymous Monk on Oct 25, 2012 at 00:06 UTC

Why would 33 be rounded down to the nearest lower multiple of 5; and 36 be rounded up to the nearest higher multiple of 5? (Ditto: 33 down to 30; but 3 up to 5?)

Alright, forget the multiple of 5 thing, its to the nearest 5 per say; therefore 33, should go to 30 because of the logic on the sample code I gave here, if the last number in this case is 3 (from 33), is less than five it should go to 30. So number 11 should go down to 10, 17 should round up to 20, I hope I am a lil clear on that now, thanks!
I hope I am a lil clear on that now, thanks!

Not really. Are you saying that

1. if it is less that xx5, it rounds down.
2. if it is greater than xx5 it rounds up.
3. But if it is equal to xx5, it stays as is?

If so, that is a very peculiar rounding mode?

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

How is 33 closer to 30 than to 35?

30 31 32 33 34 35

I count two numbers between 30 and 33, but only one number between 33 and 35. Clearly 33 is closer to 35.

Re: Best way to round a number.
by ajam (Acolyte) on Oct 25, 2012 at 00:32 UTC

It can be done with less division.

Notice 0, 1 and 2 round to 0. While 3 and 4 round up to 5. Using this knowledge, examine the number modulus 5. If its below 3 round down, otherwise round up.

Also I agree with the other comment, your examples are a bit off. For example both 33 and 36 round to 35.

```use warnings;
use strict;

sub round5 {
my (\$number) = @_;

my \$remainder = \$number % 5;

if (\$remainder < 3) {
return \$number - \$remainder;
} else {
return \$number - \$remainder + 5;
}
}

for (0..10) {
print "\$_ rounded is " . round5(\$_) . "\n";
}
Re: Best way to round a number.
by ww (Archbishop) on Oct 25, 2012 at 01:41 UTC
Actually, the "best" way to round a number may be as follows:
```perl -E "my \$num=\"33\"; say \"\$num\".'0';"
330

There appears to be some general agreement that any multiple of ten is a "round" number. If that's not a broad enough concensus, try concatenating 2, 3, 4 or 5 zeros.

This solution is scarcely more fatuous than your suggestion that the best way to round a number is "the logic on the sample code...."

Re: Best way to round a number.
by CountZero (Bishop) on Oct 25, 2012 at 07:58 UTC
Maybe not the "best" way, but very flexible: adjust the %rule hash to change the way the rounding will work based upon the last digit and the regex will do all the work (assuming you feed it a positive integer):
```use Modern::Perl;

my %rule = (
0 =>  0,
1 => -1,
2 => -2,
3 =>  2,
4 =>  1,
5 =>  0,
6 => -1,
7 => -2,
8 =>  2,
9 =>  1,
);
my @nums = 0..30;
foreach (@nums) {
print "in=\$_";
s/(\d*(\d))/\$1+\$rule{\$2}/e;
say "\t rounded=\$_";
}

CountZero

A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

My blog: Imperial Deltronics
Re: Best way to round a number.
by Marshall (Abbot) on Oct 25, 2012 at 05:15 UTC
Another possibility:
```use strict;
use warnings;

my @nums = qw (0 1 4 5 6 11 14 15 16 20 24 25 26 30 34 35 36);

foreach (@nums)
{
print "in=\$_\t rounded=", round_nearest5(\$_), "\n";
}

sub round_nearest5  # for an positive integer numeric value
{
my \$in = shift;

my (\$last_digit) = \$in =~ /(\d)\s*\$/;

if (\$last_digit <5 and \$in >= 10 )
{
\$in =~ s/(\d)\$/0/;
}
elsif (\$last_digit >=5)
{
\$in += (10-\$last_digit);
}

return \$in;
}

__END__
in=0     rounded=0
in=1     rounded=1
in=4     rounded=4
in=5     rounded=10
in=6     rounded=10
in=11    rounded=10
in=14    rounded=10
in=15    rounded=20
in=16    rounded=20
in=20    rounded=20
in=24    rounded=20
in=25    rounded=30
in=26    rounded=30
in=30    rounded=30
in=34    rounded=30
in=35    rounded=40
in=36    rounded=40
Re: Best way to round a number.
by Cristoforo (Curate) on Oct 25, 2012 at 00:41 UTC
Re: Best way to round a number.
by Perlbotics (Chancellor) on Oct 26, 2012 at 21:07 UTC

```use strict;
use warnings;

sub round5 {
my \$num = shift;

return \$num+2 - (\$num+2) % 5; # <------ TIMTOWTDI ;-)
}

for (0..10) {
printf "%3d -> %3d    %3d -> %3d\n",
\$_, round5(\$_), -\$_, round5(-\$_);
}

__DATA__

0 ->   0      0 ->   0
1 ->   0     -1 ->   0
2 ->   0     -2 ->   0
3 ->   5     -3 ->  -5
4 ->   5     -4 ->  -5
5 ->   5     -5 ->  -5
6 ->   5     -6 ->  -5
7 ->   5     -7 ->  -5
8 ->  10     -8 -> -10
9 ->  10     -9 -> -10
10 ->  10    -10 -> -10

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1000734]
Approved by davido
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2018-03-17 05:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When I think of a mole I think of:

Results (223 votes). Check out past polls.

Notices?