Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

How do I print a large integer with thousands separators?

by miblo (Initiate)
on Oct 09, 2001 at 15:28 UTC ( [id://117697]=perlquestion: print w/replies, xml ) Need Help??

miblo has asked for the wisdom of the Perl Monks concerning the following question: (data formatting)

How do I print a large integer with thousands separators?

Originally posted as a Categorized Question.

  • Comment on How do I print a large integer with thousands separators?

Replies are listed 'Best First'.
Re: How do I print a large integer with thousands separators?
by davorg (Chancellor) on Oct 09, 2001 at 15:44 UTC

    FAQ! Take a look at perlfaq5. It references Number::Format, and also shows code for a regex and a subroutine, if you'd rather not use the module.

Re: How do I print a large integer with thousands separators?
by stefp (Vicar) on Oct 10, 2001 at 05:18 UTC
    $number =~ s/(\d{1,3}?)(?=(\d{3})+$)/$1,/g;

    The lookahead (?=(\d{3})+$) ensures that the number of digits before each underscore we insert is a multiple of 3.

    An extra set of parentheses fools Perl because the regex parser barks when there are two quantifiers in a row, which is perfectly legitimate here.

    This issue was also discussed in the thread Splitting every 3 digits?.

      To do it without capturing and resubstituting, you can add a lookbehind:
      s/(?<=\d)(?=(?:\d{3})+\b)/$sep/g;
      This also works:
      substr($n, pos($n), 0) = $sep while ($n =~ /\d(?=(?:\d{3})+\b)/g);
      As does:
      substr($n, -($_*3 + ($_-1)*length($sep)), 0) = $sep for (1..int((lengt +h($n)-1)/3));
Re: How do I print a large integer with thousands separators?
by projekt21 (Friar) on Oct 09, 2001 at 15:31 UTC
Re: How do I print a large integer with thousands separators?
by dbwiz (Curate) on Jan 09, 2004 at 22:18 UTC
    $number =~ s/(?<=\d)(?=(?:\d\d\d)+\b)/,/g;
Re: How do I print a large integer with thousands separators?
by Roger (Parson) on Jan 10, 2004 at 01:17 UTC
    for ( $number ) { /\./ ? s/(?<=\d)(?=(\d{3})+(?:\.))/,/g : s/(?<=\d)(?=(\d{3})+(?!\d))/,/g; }

    This says if the number has a decimal point, end there for the purposes of commafication. Otherwise, go to the end of the string.

Re: How do I print a large integer with thousands separators?
by Jaap (Curate) on May 17, 2005 at 11:36 UTC

    Here's a simple (and quite fast) one using substr:

    my $number = 132452345; for ( my $i = -3; $i > -1 * length($number); $i -= 4 ) { substr( $number, $i, 0 ) = ','; }

Re: How do I print a large integer with thousands separators?
by Anonymous Monk on Oct 24, 2004 at 23:38 UTC

    For integers, one can avoid reverse as well as the repeated substr derivation of the remaining string in the loop:

    sub commafy_int { my $n = shift; length($n) > 3 or return $n; my $l = length($n) - 3; my $i = ($l - 1) % 3 + 1; my $x = substr($n,0,$i) . ','; while ( $i < $l ) { $x .= substr($n,$i,3) . ','; $i += 3; } $x . substr($n,$i) }
    Not using reverse also makes it much easier to convert this to work on floats (i.e. strings containing a decimal separator, '.'). To do so, simply replace any length calls above with index($n.'.','.').

Re: How do I print a large integer with thousands separators?
by jeroenes (Priest) on Oct 09, 2001 at 15:39 UTC
    Modify $#, probably (see perlvar) or use sprintf. Normally, perl prints without thousands separator.

      Camel 3 has this on page 657:

      $# [XXX,ALL] Don't use this; use sprintf instead.

      And on the previous page, "XXX" is defined as meaning:

      Deprecated, do not use in anything new.
      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you don't talk about Perl club."

      In addition to the deprecatedness of $# mentioned by davorg, how would you go about using sprintf to put thousands separators into numbers? I don't see a simple way to do this - if there was it'd be mentioned in the perlfaq to this topic, I'd guess.

      -- Hofmator

Re: How do I print a large integer with thousands separators?
by Anonymous Monk on Jan 31, 2004 at 05:11 UTC
    I benchmarked the following methods

    'while loop' is the "1 while..." method.
    'reverse' is the Andrew Johnson method.
    'lookahead' is the stefp method.
    'manual' is the one using substr.
    'le3manual' is the one using substr with an initial check to make sure there are more than three digits.

    Number:324898x10^88x10^13
    while loop:869k/s60k/s33k/s18k/s
    reverse:465k/s65k/s47k/s34k/s
    lookahead:571k/s54k/s34k/s22k/s
    manual:270k/s139k/s95k/s61k/s
    le3manual:1000k/s135k/s91k/s59k/s

    Nk/s = N thousands of completed commafications per second

    Basically it looks like the substr method, with the <=3 clause, obliterates the competition. I feel dirty saying it, but looks like a one-liner regexp is not the best solution.

    (My test script is available here)
      Your test script was very educational for me. I'd never seen use of the Benchmark module before. It looks like you've certainly gotten a fast method for adding in the thousands separators.

      For those who need something a bit easier to follow, I'd like to add the following to this topic:
      #!/usr/bin/perl use Number::Format; my $num = 12349329824342; my $nf = new Number::Format(-thousands_sep => ','); my $separated_num = $nf->format_number($num);
Re: How do I print a large integer with thousands separators?
by hanspoo (Initiate) on Oct 26, 2004 at 23:44 UTC
    $num = 123456789; $num = reverse $num; # reverse the number's digits $num =~ s/(\d{3})/$1,/g; # insert comma every 3 digits, from beginning $num = reverse $num; # Reverse the result $num =~ s/^\,//; # remove leading comma, if any
Re: How do I print a large integer with thousands separators?
by Anonymous Monk on Aug 15, 2003 at 12:32 UTC
    my $number = '$12345678.90'; # dollars $_ = reverse $number; s/(\d{3})(?=\d)(?!\d*\.)/$1,/g; $number = reverse $_;
Re: How do I print a large integer with thousands separators?
by Anonymous Monk on Jan 09, 2004 at 15:13 UTC
    sub puntato { my $n=reverse($_[0]); my $x=''; while(length($n)>3) { $x=$x.substr($n,0,3).'.'; $n=substr($n,3); } $x=reverse($x.$n); return($x); }
      How about this?
      sub puntato{ my $z=reverse $_[0];$z=~s/(\d{3})(?=\d)/$1\./g;scalar(rev +erse($z))}
      Boris
Re: How do I print a large integer with thousands separators?
by hdb (Monsignor) on May 27, 2013 at 19:05 UTC
    $number = 123456789; $number = reverse join ",", (reverse $number) =~ /(\d{1,3})/g;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://117697]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (5)
As of 2024-04-23 18:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found