Thread: Injecting commas to long numbers?

Page 1 of 2 12 Last
1. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Jul 2003
Posts
35
Rep Power
12

Injecting commas to long numbers?

Hi all,

Anyone know of a built-in or easy way to turn a number like 3961037749 into the string "3,961,037,749"?

Thanks,
tps
2. There might be a betetr way to do this but i'm not aware of it if there is.. sooo, i've writen a few different versions of the inject functions.

Code:
```def inject(number):
string = str(number)
cursor = 0
output = []

for number in string[::-1]:
if not cursor % 3:
number = number + ','
cursor = cursor + 1
output.append(number)

output.reverse()

return ''.join(output)[:-1]```
Code:
```def inject(number):
string = str(number)
output = []

for index, value in enumerate(string):
if not index % 3:
value = string[index - len(string)] + ','
output.append(value)
return ''.join(output)[:-1]```
I'm also gonna see if this can be done with list comprehensions. We'll see

Mark.
Last edited by netytan; February 12th, 2004 at 05:26 PM.

Code:
```def insert(i, v):
if not i % 3: v = v + ','; return v

def inject(n):
return ''.join([insert(i, v) for i, v in enumerate(str(n))])[:-1]```
Obviously using list comprehensions . Which has its limitations. Still works though , although personally i'd use one of the functions above.

Mark.
Last edited by netytan; February 12th, 2004 at 05:25 PM.
4. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2001
Location
Houston, TX
Posts
383
Rep Power
13
netytan: FYI, it's list comprehensions, not compressions
5. Hahhaha i so didn't spot that need to think more . Ah it could be worse though, this guy i used to work for couldnt stop himself typing sausage instead of some word... every time he tried to type this word he'd type sausage lol

Mark.
6. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Jul 2003
Posts
133
Rep Power
12
Here's a nice and uncomplicated implementation that might be fun to parse:
Code:
```def commatize(num):
if type(num) is not str:
num = str(num)
return ",".join([part for part in\
[num[x*-3:len(num)+3+(x*-3)]
for x in range(1, len(num) / 3 + 2)][::-1]
if len(part) != 0])```
This is the true one-liner, considering that you could easily remove the "if type..." part of the code. On the other hand: I too would rather use the more verbose code.
Last edited by percivall; February 12th, 2004 at 06:07 PM.
7. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2001
Location
Houston, TX
Posts
383
Rep Power
13
Another version, just for fun:
Code:
```def commatize(num):
L = list(str(num))
for add, pos in enumerate(range(3, len(L), 3)):
return ''.join(L)```
it's sort of the one-function version of netytan's shortest.
8. Just adding to the mix
The Good :
Code:
```def comma5(num):
d = `num`[::-1]
r = ''
for c in range(0,len(d),3):
r = r+d[0:3]+','
d = d[3:]
if r[-1] == ',':
r = r[:-1]
return r[::-1]```
The Bad and the Ugly(ist) code I've ever written
Code:
```def comma3(num):
d= ''.join(map(lambda x, y : x+[',',''][(y+1)%3 and 1],list(`num`)[::-1],range(len(list(`a`)))))
return d[:len(d)-(d[-1]==',')][::-1]```
comma5 is fast, comma3 is SO slow.
Grim
9. Ok i finally got it figured it out, with a little inspiration from you're examples.

No i don't clame its the most efficent function because i can see places that could be improved on i.e. the two str() calls would normally be singular, but since the aim of this example was to write a totaly self contained one liner it had to be so.

Code:
`def inject(number): return ','.join([str(number)[::-1][index:index + 3][::-1] for index in range(0, len(str(number)), 3)][::-1])`
If you can see ways to shorten this further i'd love to hear them.

Grim: way, you were right, you can do this with map and lambda *shakes you're hand as promised*

Mark.
10. Netyan,full marks for
But, my comma5 is still twice as fast as the worst posted (my comma3 func ) and 40% faster than the next best
Grim
11. No Profile Picture
Contributing User
Devshed Intermediate (1500 - 1999 posts)

Join Date
Feb 2004
Location
London, England
Posts
1,585
Rep Power
1373

A recursive alternative

All the solutions given so far work by treating the number as a string or list of characters, and chopping it up/inserting characters.

Here is an alternative that works by recursively dividing the number by 1000:

Code:
```>>> def comma(x): return x < 1000 and str(x) or ('%s,%03d' % (comma(x//1000), (x%1000)))
...
>>> comma(30498523409562345923459085340L)
'30,498,523,409,562,345,923,459,085,340'```
I have not benchmarked it against the other versions - that is left as an exercise for the reader.

The function also only works with positive integers. It can be made to work with negative numbers, but would not be such a neat one-liner.

Dave - The Developers' Coach
Last edited by DevCoach; February 19th, 2004 at 12:37 PM. Reason: fixed typo in the code
12. Dave, that must be the last word in compactness and speed. A full 6% faster than my best effort
Another one to hurt my head
Grim
Last edited by Grim Archon; February 19th, 2004 at 05:35 PM. Reason: Added facts.
13. No Profile Picture
Contributing User
Devshed Intermediate (1500 - 1999 posts)

Join Date
Feb 2004
Location
London, England
Posts
1,585
Rep Power
1373

improved recursive version

I have played around with this some more, and done some benchmarking. I found that two of the given solutions did not run, and two others gave the wrong answers for long integers (because the conversion to string added an 'L' on the end, which screwed up their indexing).

Of the ones that ran, my version was fastest for integers and grim's comma5 function was slightly faster for longs.

However all the functions so far failed for negative numbers - mine just returned the number unchanged, and all the others (that worked) when given a number like:

-450324598

returned:

-,450,324,598

here is a new version of my recursive function that correctly handles all cases, and has been re-written to be easier to read (this is Python after all, not Perl)

Code:
```def comma(x):
if x < 0: return '-' + comma(-x)
if x < 1000: return str(x)
return '%s,%03d' % (comma(x//1000), (x%1000))```
Incidentally, the '//' operator is the 'floor division' operator introduced in 2.2 - for earlier versions of Python use '/'. At the moment they both give the same result, but in the future (I think in 2.4) the '/' operator on integers will convert the answer to a float when necessary.

Have a nice day

Dave - The Developers' Coach
14. Here's my version fixed for the issues Dave mentioned and with a minor speed tweak
Code:
```def comma5(num):
if num < 0: return '-' + comma5(-num)
d = `num`[::-1]
r = ''
for c in range(type(num)==type(1L),len(d),3):
r += d[c:c+3]+','
if r[-1] == ',':
r = r[:-1]
return r[::-1]```
results for calling each function 100,000 times show that for everyday numbers, Dave's method is fastest:
Code:
```                                  Number  comma5  comma   Diff%
1 | 1.410 | 0.277 |-80.362
4,096 | 1.630 | 0.858 |-47.390
16,777,216 | 1.803 | 1.351 |-25.052
4,294,967,296 | 2.019 | 2.161 |7.065
68,719,476,736 | 2.026 | 2.177 |7.435
1,099,511,627,776 | 2.155 | 2.727 |26.539
1,152,921,504,606,846,976 | 2.476 | 3.840 |55.069
4,722,366,482,869,645,213,696 | 2.649 | 4.409 |66.481
75,557,863,725,914,323,419,136 | 2.673 | 4.427 |65.626```
The switch from integer to long has an impact in Dave's method at which point the string method becomes best. With a very small performance hit to each method the following hybrid makes a good compromise for best overall performance with the current math libraries:
Code:
```def comma_hybrid(num):
if num < 0: return '-' + comma_hybrid(-num)
if num < 1000: return str(num)
if num > 2147483647:
d = `num`[::-1]
r = ''
for c in range(type(num)==type(1L),len(d),3):
r += d[c:c+3]+','
if r[-1] == ',':
r = r[:-1]
return r[::-1]
return '%s,%03d' % (comma_hybrid(num//1000), (num%1000))```
Grim
15. No Profile Picture
Contributing User
Devshed Newbie (0 - 499 posts)

Join Date
Dec 2001
Location
Houston, TX
Posts
383
Rep Power
13
Originally Posted by Grim Archon
Code:
`    if num > 2147483647:`
I'm guessing you've never seen sys.maxint
Page 1 of 2 12 Last