Is there somewhere hidden in a (small) module a function, which does this for me:
my $var = 23654325432;
$var = reverse $var;
$var =~ s/\d{3}\K(?=\d+)/_/g;
$var = reverse $var;
I like Number::Format but it didn't pass all tests on windows.
use Number::Format;
my $nf = new Number::Format(
-thousands_sep => ',',
-decimal_point => '.',
);
my $formatted = $nf->format_number( 23142153 );
Look at perl5i. It has commify
and group_digits
methods.
The fastest method is in the perlfaq
( perldoc -q commas
):
sub commify {
local $_ = shift;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
return $_;
}
Of course, I just came up with a function that beats this one by ~70%.
use constant THOU_SEP => ',';
use English qw<@LAST_MATCH_START @LAST_MATCH_END>;
sub ss_commify {
my $s = shift;
return $s unless $s =~ m/\d{4,}/;
my ( $f, $p ) = ( $LAST_MATCH_START[0], $LAST_MATCH_END[0] );
my $ts = THOU_SEP;
# |-- That is, replace a *0-length* substring at $p with the
# v thousand separator
substr( $s, $p, 0, $ts ) while ( $p -= 3 ) > $f;
return $s;
}
And it works with whatever text you have in front or back. The FAQ version just works with text in back (admittedly a numeric value in Perl).
The idea is find what you want to work on with the regex once and then simply use Perl's elastic string implementation to do the perfunctory work. A substitution for each of these seems to be a bit more overhead than necessary.
I use
$num =~ s/(\d) (?= (?:\d{3})+ \b )/$1,/gx;
which just adds a comma after every digit that is followed by a multiple of three digits.
If you'd like a function instead:
sub commify {
(my $num = $_[0]) =~ s/(\d) (?= (?:\d{3})+ \b )/$1,/gx;
$num;
}
print commify(10 ** $_), "\n" for 1 .. 14;
OUTPUT
10
100
1,000
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
10,000,000,000
100,000,000,000
1,000,000,000,000
10,000,000,000,000
100,000,000,000,000