The code below should work. I've tried it on a bunch of numbers. Its disappointing that it needs the extra checks for numbers less than 100, but that rounding is degenerate compared to the rest of the algorithm. Without those checks, 12 rounds to 12.5 - which is definitely wrong
{
my $number = $ARGV[0];
my $floor_log = int( log10($number) );
my $category = 10**$floor_log;
my $as_decimal = $number / $category;
my $integer_part = int($as_decimal);
my $decimal_part = $as_decimal - $integer_part;
my $rounded = $integer_part;
if ( ($number >= 100) && ($decimal_part < 0.25) ) {
$rounded += .25;
}
elsif ( $decimal_part < 0.5 ) {
$rounded += .5;
}
elsif ( ($number >= 100) && ($decimal_part < 0.75) ) {
$rounded += .75;
}
else {
$rounded += 1;
}
$rounded *= $category;
print "number = $number\n";
print "rounded = $rounded\n";
}