sub nearest { local $_ = 0+$_[0]; return 0 unless $_; my $f = $_ <=> 0; $_ = abs($_); while ($_ >= 10) { $_ /= 10; $f *= 10; } while ($_ < 1) { $_ *= 10; $f /= 10; } return int($_ + 0.5) * $f; } sub up_nearest { local $_ = 0+$_[0]; return 0 unless $_; my $f = $_ <=> 0; $_ = abs($_); while ($_ >= 10) { $_ /= 10; $f *= 10; } while ($_ < 1) { $_ *= 10; $f /= 10; } return (int($_) == $_ ? $_ : (int($_) + 1)) * $f; } foreach ( 0, 5, 10, 50, 0.1, 5.1, 11, 51, 0.11, 5.5, 15, 55, 0.15, 5.9, 19, 59, 0.19, ) { printf("%12.6f: %4s\n", $_, nearest( $_)); printf("%12.6f| %4s\n", $_, up_nearest( $_)); printf("%12.6f: %4s\n", -$_, nearest(-$_)) if $_; printf("%12.6f| %4s\n", -$_, up_nearest(-$_)) if $_; }