evalEmpire / perl5i

A single module to fix as much of Perl 5 as possible in one go
http://search.cpan.org/perldoc?perl5i
Other
156 stars 42 forks source link

Making round more flexible #227

Open dhorne opened 11 years ago

dhorne commented 11 years ago

As noted in issue #95, round simply rounds to the nearest integer. It would be ideal if we could provide an optional parameter to specify the number of decimal places, particularly when dealing with financial values. Numbers ending in 5.6,7,8,9 round up, numbers ending in 0,1,2,3,4 round down.

For my own needs, the round function I have been using is:

func round($number, $places) {
    my $sign = ($number < 0) ? '-' : '';
    my $abs = abs($number);    
    if ($places < 0) {
        $places *= -1;
        return $sign
          . substr($abs + ("0." . "0" x $places . "5"),
            0, $places + length(int($abs)) + 1);
    } else {
        my $p10 = 10**$places;
        return $sign . int($abs / $p10 + 0.5) * $p10;
    }
}

And the results are

say round(5.6255, -3); # 5.626 say round(5.6254, -3); # 5.625 say round(5.6254, 0); # 6 say round(5.6254, 1); # 10 say round(5.6254, 2); # 0

schwern commented 11 years ago

Sounds good to me. A few caveats... change the interface to take a hash of options, use wrap as the example. Then we can add more options later. It would be nice if ceil and floor were given the same treatment, but not a blocker.

Code is in perl5i::2::SCALAR.

schwern commented 11 years ago

PS You are a collaborator now. It's preferable you do the work in a branch on the main repository, then other collaborators can work directly on the branch. The naming convention is issue/227.

notbenh commented 11 years ago

If we are going to super charge round then I would suggest separating the idea of round to nearest and round to precision. I will present these as other round methods mostly as a way to explain rather then a suggestion of implementation:

13->round_to_nearest(5) should be 15 1.23->round_to_nearest(.05) should be 1.25

Having a round_to_nearest then would negate the need to have the positive precision from the example code thus allowing us to just have something like this:

5.6255->round_to_precision(3) should be 5.626