String formatting (%)

P

Pascal

Hello,
I've a float number 123456789.01 and, I'de like to format it like this
"123 456 789.01".
Is this possible with % character?
 
L

Larry Bates

Pascal,

Here is a function that I had that does what you want.
Warning-If the floats get very large it breaks down.

Larry Bates
Syscon, Inc.

def fmt_wspaces(amount):
#
# This function will take the number passed to it and format it with
# spaces as thousands separators.
#
# If I got zero return zero (0.00)
#
if not amount: return '0.00'
#
# Handle negative numbers
#
if amount < 0: sign="-"
else: sign=""
#
# Split into fractional and whole parts
#
whole_part=abs(long(amount))
fractional_part=abs(amount)-whole_part
#
# Convert to string
#
temp="%i" % whole_part
#
# Convert the digits to a list
#
digits=list(temp)
#
# Calculate the pad length to fill out a complete thousand and add
# the pad characters (space(s)) to the beginning of the string.
#
padchars=3-(len(digits)%3)
if padchars != 3: digits=tuple(padchars*[' ']+digits)
else: digits=tuple(digits)
#
# Create the mask for formatting the string
#
sections=len(digits)/3
mask=sections*" %s%s%s"
if _debug > 2: logf.writelines("D","mask=%s" % mask)
outstring=mask % digits
#
# Drop off the leading space and add back the sign
#
outstring=sign+outstring[1:].lstrip()
#
# Add back the fractional part
#
outstring+="%.2f" % fractional_part
#
return outstring

if __name__=="__main__":

print "----------testing negative floats------------------------------"
sign=-1
invalue=0L
for j in range(2):
for i in range(1,10):
invalue=invalue*10+i
print fmt_wspaces(float(sign*invalue)-.01)

print "----------testing positive floats------------------------------"
sign=1
invalue=0L
for j in range(2):
for i in range(1,10):
invalue=invalue*10+i
print fmt_wspaces(float(sign*invalue)+.01)
 
V

vincent wehren

Pascal said:
Hello,
I've a float number 123456789.01 and, I'de like to format it like this
"123 456 789.01".
Is this possible with % character?

The following should do what you want, although the commafy_float I
quickly added is probably a little naive:


def commafy(numstring, thousep=","):
"""
Commafy the given numeric string numstring

By default the thousands separator is a comma
"""
numlist = list(numstring)
numlist.reverse()
tmp = []
for i in range(0, len(numlist), 3):
tmp.append("".join(numlist[i:i+3]))
numlist = thousep.join(tmp)
numlist = list(numlist)
numlist.reverse()
return "".join(numlist)

def commafy_float(flStr, thousep=","):
whole, dec = flStr.split(".")
return ".".join([commafy(whole, thousep=thousep)
, dec])

if __name__ == "__main__":

units = "56746781250450"
unitsWithThouSeps = commafy(units)
print unitsWithThouSeps
aFloatAsString = "1128058.23"
aFloatAsStringWithThouSeps = commafy_float(aFloatAsString
,thousep=" ")
print aFloatAsStringWithThouSeps


Regards

-- Vincent Wehren
 
D

Daniel 'Dang' Griffith

No, as shown by http://docs.python.org/lib/typesseq-strings.html
but you could probably use the 'locale' module instead.

I suspect there's also a regular expression that could deal with
that, but I don't want to know what it is. ;-)

-Peter
Since you don't want to know what it is, I'll at least tell you
where it is: In Mastering Regular Expressions by Jeffrey E. F. Friedl.
I don't have it front of me, but it's the "commafying" example. A
quick search of the author's site looks like it's on pgs 64-65.
Of course, the OP would substitute spaces for the commas.
--dang
 
P

Peter Hansen

Daniel said:
Since you don't want to know what it is, I'll at least tell you
where it is: In Mastering Regular Expressions by Jeffrey E. F. Friedl.
I don't have it front of me, but it's the "commafying" example. A
quick search of the author's site looks like it's on pgs 64-65.

Thank you. You can even get the code listings online, which is
very nice since my copy has migrated into a closet during a recent
move.
'21,421,906.12'

Of course, the OP would substitute spaces for the commas.
'21 421 906.12'

Very nice... quite elegant, I suppose. I struggled with it a
bit myself yesterday but I'm no RE expert. :-(

-Peter
 
A

A. Lloyd Flanagan

Hello,
I've a float number 123456789.01 and, I'de like to format it like this
"123 456 789.01".
Is this possible with % character?

No, but this works with integers. Not sure how it compares to the
other approaches mentioned. You could adapt it to do floats by
stopping at the decimal point:

def addCommas(aNumber):
if len(aNumber) < 4: return aNumber
#how many digits before first ,?
prefix = len(aNumber) % 3
#need special case if digits is multiple of 3
if prefix == 0: prefix = 3
result = [aNumber[:prefix]]
for a in range(len(aNumber) / 3):
#get next 'segment' of three digits
segment = aNumber[prefix + 3*a: prefix + 3*a + 3]
if segment: #can be '' if len(aNumber) divisible by 3
result.append(segment)
return ','.join(result)

I'm sure this can be improved.
 
P

Peter Hansen

Peter said:
'21 421 906.12'

And in case the OP is entirely unfamiliar with regular
expressions, you wouldn't actually do a separate "replace"
operation like the above, so

re.sub(r'(?<=\d)(?=(\d\d\d)+\.)', ' ', s)

should work nicely, at least with any floating that *always*
has a decimal point present. If the numbers might sometimes
not have a decimal point, I think this will do the job, so
it's a more general solution:

re.sub(r'(?<=\d)(?=(\d\d\d)+(\.|$))', ' ', s)

Note that addition of an alternate for \. at the end of the pattern.

-Peter
 
B

Bengt Richter

No, as shown by http://docs.python.org/lib/typesseq-strings.html
but you could probably use the 'locale' module instead.

I suspect there's also a regular expression that could deal with
that, but I don't want to know what it is. ;-)

If you are willing to use a special name mod (you can choose it), you
can get there with % and a commafy that stuffs spaces instead of commas ;-)
... def __init__(self, d): dict.__init__(self, d)
... def __getitem__(self, name):
... if name.startswith('cfy_'):
... return commafy(self.get(name[4:],'??'))
... else: return self.get(name,'??')
... ... sign, val = '-'[:val<0], str(abs(val))
... val, dec = (val.split('.')+[''])[:2]
... if dec: dec = '.'+dec
... rest = ''
... while val: val, rest = val[:-3], '%s %s'%(val[-3:], rest)
... return '%s%s%s' %(sign, rest[:-1], dec)
... 'x: -12345.678 cfy_x: -12 345.678'

And the OP's example:
'x: 123456789.01 cfy_x: 123 456 789.01'

Regards,
Bengt Richter
 
P

P Adhia

(e-mail address removed) (A. Lloyd Flanagan) wrote in message

Another version of a more compact function would be,

def commafy(s):
return len(s) > 3 and "%s,%s" % (commafy(s[:-3]), s[-3:]) or s

Note that this function accepts string representation of an integer
(without checks of course).

P Adhia
 
A

A. Lloyd Flanagan

Another version of a more compact function would be,

def commafy(s):
return len(s) > 3 and "%s,%s" % (commafy(s[:-3]), s[-3:]) or s

Note that this function accepts string representation of an integer
(without checks of course).

P Adhia

And it seeems to work beautifully. Thanks, that's a great improvement.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top