Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Commify numbers, the boring and straightforward way

by Aristotle (Chancellor)
on Mar 02, 2005 at 06:51 UTC ( #435711=snippet: print w/replies, xml ) Need Help??

The well-known commifying snippet from the perlfaq5 is tricky enough to understand; the recent addition in that answer is much worse. And all of the other snippets I've seen use regex contortions to get the job done as well. Why?

The following is completely clear and straightforward, yet as I'm surprised to find, it seems noone else has posted something along these lines so far.

Update: of course it was supposed to be scalar reverse in both instances.

Update: this original version doesn't correctly handle anything but a string of digits:

sub commify { scalar reverse join ',', unpack '(A3)*', scalar reverse shift }

Update: gack, I need to sleep. Fixed three instances of reverse scalar that were supposed to be scalar reverse.

sub commify {
    my ( $sign, $int, $frac ) = ( $_[0] =~ /^([+-]?)(\d*)(.*)/ );
    my $commified = (
        scalar reverse join ',',
        unpack '(A3)*',
        scalar reverse $int
    return $sign . $commified . $frac;
Replies are listed 'Best First'.
Re: Commify numbers, the boring and straightforward way
by holli (Monsignor) on Mar 02, 2005 at 08:00 UTC
    There is a module for that, namely Number::Format. And (shameless self advertise) itīs extension Number::Format::Calc, with wich you can do calculations with commifies numbers.

    holli, /regexed monk/

      That is neat. However, unless I actually need the flexibility that module provides, I don't think saving 6 or 7 lines of code is worth an added dependency. That sort of issue crops up with other only nearly trivial stuff like a file slurping function too.

      Makeshifts last the longest.

Re: Commify numbers, the boring and straightforward way
by jmcnamara (Monsignor) on Mar 02, 2005 at 08:53 UTC

    Unfortunately, this would only work for integer style numbers and not for floating point numbers as handled by the faq example:
    my $n = 23659019423.233; print "GOT: ", commify($n), "\n";


      Good point. And I just noticed that it doesn't properly treat signs either. Still boring and straightforward, if not quite so trivial:

      sub commify { my ( $sign, $int, $frac ) = ( $_[0] =~ /^([+-]?)(\d*)(.*)/ ); my $commified = ( reverse scalar join ',', unpack '(A3)*', scalar reverse $int ); return $sign . $commified . $frac; }

      It should behave exactly like the FAQ code, and some shallow testing seems to confirm that.

      Makeshifts last the longest.

        Sometimes I rewrite a little snip of confusing code, and I fall in love with my new "more elegant" solution. Then after some sleep, I realize that my new solution is just as ugly as the version I replaced, and less battle-tested.

        With respect for your discussion and skills, I must admit that to me, this code doesn't look better than (either of) the perlfaq5 examples. It doesn't look worse, but it is not a pearl of truth in the darkness, either. Your code and that code both take a bit of time to get to understand why each statement is justified, and how it deals with edge cases. I don't see an improvement, I just see a difference.

        The first time I became a manager, I had to learn how to accept that other people do things in a way that I would not have done them. If it passes the tests, and it's not a risk to maintenance, then I would just have to let it be. I'd have to accept the solution until there was a real need to change it, and there rarely was. If I didn't learn to accept others' solutions, I'd end up coding it all myself. It's a hard hurdle to cross but it's a worthwhile one.

        [ e d @ h a l l e y . c c ]

Re: Commify numbers, the boring and straightforward way
by eyepopslikeamosquito (Chancellor) on Mar 02, 2005 at 08:04 UTC

    Very nice! This requires perl 5.8.0 and above. When I ran it with perl 5.6.1 and perl 5.005 I got the error message:

    Invalid type in unpack: '(' at line 3.
    Update: from perl58delta: "pack() / unpack() can now group template letters with () and then apply repetition/count modifiers on the groups". Also, I think you need to reverse the reverse and scalar. Running:
    use strict; sub commify { reverse scalar join ',', unpack '(A3)*', reverse scalar shift; } sub commify2 { scalar reverse join ',', unpack '(A3)*', reverse scalar shift; } my $x = commify(1234); my $y = commify2(1234); print "x='$x' y='$y'\n"; print "comm :", commify(1234), ":\n"; print "comm2:", commify2(1234), ":\n";
    x='1,234' y='1,234' comm :432,1: comm2:1,234:
Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://435711]
and all is calm...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2018-06-20 12:19 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (116 votes). Check out past polls.