in reply to Fuzzy How-Many

When I play the role of a human explaining a number, I tend to round up the absolute value at some fuzzy index of that number. After the round-up, anything that follows that index is zero-ed out.
sub fuzz { my $n = shift(); return unless defined($n); my $neg = ($n < 0); ($n) = ($n =~ /(\d+)/); $n += 0; my ($c1, $c2) = ($n =~ /^(\d{0,2}\d{3})((?:\d{3})*)$/); return $neg ? -$n : $n unless defined($c1); my $c3 = substr($c1, -3, 2, ""); my $c4 = substr($c1, -1, 1, ""); my $n2 = $c1 . $c3; my $x1 = 100 - $c3; my $x2 = (10 - $c3 % 10) % 10; $n2 += $c1 ? ( ($x1 <= 30 && $c1 >= 10) ? $x1 : $x2 ? $x2 : $c4 ? 1 : 0 ) : ($c4 ? 1 : 0); $n2 .= 0 x (length($c2) + 1); return $neg ? -$n2 : $n2; }

The tests explain better than words:

use Test::More; # same behavior for -ve numbers as +ve ones is( fuzz(-721), -730 ); is( fuzz(-98), -98 ); is( fuzz(-2), -2 ); # fractions ignored is( fuzz(-0.5), 0 ); is( fuzz(0.005), 0 ); is( fuzz(0.9), 0 ); # up to 2 digits returned as-is is( fuzz(0), 0 ); is( fuzz(3), 3 ); is( fuzz(9), 9 ); is( fuzz(96), 96 ); # 3 digits is( fuzz(120), 120 ); is( fuzz(123), 130 ); is( fuzz(721), 730 ); is( fuzz(809), 810 ); is( fuzz(980), 980 ); is( fuzz(993), 1000 ); # 4 digits is( fuzz(1234), 1300 ); is( fuzz(1720), 1800 ); is( fuzz(3990), 4000 ); is( fuzz(9910), 10000 ); # 5 digits is( fuzz(18433), 18500 ); is( fuzz(21250), 21300 ); is( fuzz(21750), 22000 ); is( fuzz(99800), 100000 ); # 6 digits follow 3-digit behavior # 7 digits follow 4-digit behavior and so on is( fuzz(123_555), 130_000 ); is( fuzz(219_900), 220_000 ); is( fuzz(633_999), 640_000 ); is( fuzz(1_234_567), 1_300_000 ); is( fuzz(99_402_888), 99_410_000 ); is( fuzz(99_611_222), 99_700_000 ); is( fuzz(99_704_567), 100_000_000 ); done_testing();