Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

RE: regexp for adding commas to a number

by merlyn (Sage)
on Aug 17, 2000 at 20:42 UTC ( [id://28335]=note: print w/replies, xml ) Need Help??


in reply to regexp for adding commas to a number

That's not a working regex. The best ones work something like this:
$number=1234567; # with commas, should be "1,234,567" $number =~ s/(\d)(?=(\d{3})+(\D|$))/$1\,/g;
Notice the missing inner repetition in the previous post? And I'm doing this with lookahead, so I can scan from left to right. The "1 while ..." solutions scan effectively from right to left, so they may be slower. Actually, I'd be interested in the various benchmarks on these. {grin}

-- Randal L. Schwartz, Perl hacker

Replies are listed 'Best First'.
RE: RE: regexp for adding commas to a number
by AltBlue (Chaplain) on Aug 17, 2000 at 23:45 UTC

    great regex! me too have forgoten about the look-ahead assertion :( my function that does number beautifying has no less than 8 lines :((
    still.. there's a little problem when handling floats: the digits after the dot shouldn't be 'beautified' :(
    .. i tried to enhance a little your line but the problem still remains because of the fixed-width look-behind:

    $number =~ s/(?<!\.\d)(\d)(?=(\d{3})+(\D|$))/$1,/g;
    (this example works for numbers with 5 digits after the dot... variations may me done by modifying the 'quantity' of \d from the look-behind assertion)

    couldn't think at anything better now.. maybe you have another bright idea for this too o=)

    so, after inserting your wizcraft, my lame tool looks something like this:

    $number =~ s/(\d+)(\.\d+)?/bea_int($1).$2/eg; sub bea_int { my $kk = $_[0]; $kk =~ s/(\d)(?=(\d{3})+(\D|$))/$1\,/g; return $kk; }

    --
    AltBlue... w8ing 4 a better solution o=Q

      The easy way to deal with open ended floating pointed nums is to simply remove the floating part until the commas are added, then reattach.
      $integer =~ s/(.*)(\.\d\d+)$/$1/; $float = $2; # do stuff $integer .= $float;
        lol. isn't that what i'm currently doing ?! :))
        plz check up again my previous post and look at the final code - it does exactly that :)
        your snippet doesn't work for 'real' strings like: 'for every 1234.567 blah stuff there is some 34% rate of foobar success at every 9876543.876543 seconds'

        --
        AltBlue.

        It would be more efficient to use split.
        my( $int, $float ) = split /\./, $num;
Re^2: regexp for adding commas to a number
by Deven (Novice) on Feb 25, 2022 at 04:26 UTC
    This regex continues adding commas after a decimal point if there are at least 4 decimal places. It also does repeated lookahead checks for multiples of 3 digits. I came up with a better regex using a single lookahead for the multiple of 3 digits and using \G to stay in sync thereafter, and not continuing past a decimal point. Here's what I ended up with:
    $number =~ s/(^\D*\d{1,3}(?=(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
    For example, "12345678.9012345" becomes "12,345,678.9012345" instead of "12,345,678.9,012,345". Of course, after I came up with this, I saw the current perlfaq5 and saw an extremely similar example there from Benjamin Goldberg:
    s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
    Oh well, I guess it wasn't a new idea after all! His version adds the (?>...) non-backtracking construct, which is definitely an improvement over mine. He only matched a sign at the beginning, which is reasonable. I had [+-]? at one point, but it occurred to me that a monetary value might already have a dollar sign prefixed to the number, so I used \D* instead. I think it's a wash to use \d+? instead of \d{1,3} as I had -- it prefers checking for 1 digit first instead of 3 digits, but there's no way to know which of the 3 will match. If I changed mine to \d{1,3}? then it would be functionally equivalent.
(Kozz) RE: RE: regexp for adding commas to a number
by Kozz (Friar) on Aug 17, 2000 at 21:25 UTC
    Thanks for the insight. I'm ignorant of the secrets of lookahead, lookbehind, inner repetitions, and all the other associated voodoo with things like this, so while this regex certainly works, the breakdown of what it all means is a mystery to me. Would "Mastering Regular Expressions" be a good teacher for this sort of thing?

    Thanks, merlyn (++), and everybody else for their help and insight.
      The currently available Mastering Regular Expressions doesn't cover any of the really cool Perl 5 regex stuff. Jeffrey Friedl is in the process of rewriting the book for a second edition, and has been working with the Perl developers to uncover inconsistencies in the implementation (what normal people would call "bugs" {grin}) and gaps in the documentation.

      Don't hold your breath though. I know this effort will probably take one to two years of nights and weekends. "Been there Done that" x $n

      -- Randal L. Schwartz, Perl hacker

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-03-29 00:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found