How can I print a float with thousands separators?
Question:
How can I format a decimal number so that 32757121.33
will display as 32.757.121,33
?
Answers:
Use locale.format()
:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'German')
'German_Germany.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32.757.121,33
You can restrict the locale changes to the display of numeric values (when using locale.format()
, locale.str()
etc.) and leave other locale settings unaffected:
>>> locale.setlocale(locale.LC_NUMERIC, 'English')
'English_United States.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32,757,121.33
>>> locale.setlocale(locale.LC_NUMERIC, 'German')
'German_Germany.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32.757.121,33
If you can’t or don’t want to use locale
for some reason, you can also do it with a regular expression:
import re
def sep(s, thou=",", dec="."):
integer, decimal = s.split(".")
integer = re.sub(r"B(?=(?:d{3})+$)", thou, integer)
return integer + dec + decimal
sep()
takes the string representation of a standard Python float and returns it with custom thousands and decimal separators.
>>> s = "%.2f" % 32757121.33
>>> sep(s)
'32,757,121.33'
>>> sep(s, thou=".", dec=",")
'32.757.121,33'
Explanation:
B # Assert that we're not at the start of the number
(?= # Match at a position where it's possible to match...
(?: # the following regex:
d{3} # 3 digits
)+ # repeated at least once
$ # until the end of the string
) # (thereby ensuring a number of digits divisible by 3
I have found another solution:
'{:,.2f}'.format(num).replace(".","%").replace(",",".").replace("%",",")
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8')
'en_GB.UTF-8'
>>> print(locale.format_string('%.2f', 12742126.15, True))
12,742,126.15
This sample code works for GB in a docker container.
FROM python:3.8.2-slim-buster
RUN apt-get update && apt-get install -y locales &&
sed -i -e 's/# en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen &&
dpkg-reconfigure --frontend=noninteractive locales
ENV LANG en_GB.UTF-8
ENV LC_ALL en_GB.UTF-8
Locales could be found by running the following command on your terminal (Linux Dirstro)
locale -a
Then a full list of locales appear:
en_AG.utf8
en_AU.utf8
...
en_GB.utf8
...
I liked def sep...
, but it doesn’t change the problem of finding the local format for numbers automatically. That is really what you want if you don’t want to add lots of code to your reporting.
You could use
g.periodsOrCommas={'thou':'.','dec':','}
where g is a globally available area.
change sep to:
def sep(s:str):
thou=g.periodsOrCommas['thou']
dec= g.periodsOrCommas['dec']
Then as part of the program setup, or an inquiry to the user, set periods and commas to the required formats. In all reports or windows, call sep to deal with floating point representation.
Lastly, you could have options in sep to specify the number of decimal places, or even the type of formatting needed. But that is way off the current question.
Thanks for a great solution to an actual problem I was facing.
How can I format a decimal number so that 32757121.33
will display as 32.757.121,33
?
Use locale.format()
:
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'German')
'German_Germany.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32.757.121,33
You can restrict the locale changes to the display of numeric values (when using locale.format()
, locale.str()
etc.) and leave other locale settings unaffected:
>>> locale.setlocale(locale.LC_NUMERIC, 'English')
'English_United States.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32,757,121.33
>>> locale.setlocale(locale.LC_NUMERIC, 'German')
'German_Germany.1252'
>>> print(locale.format('%.2f', 32757121.33, True))
32.757.121,33
If you can’t or don’t want to use locale
for some reason, you can also do it with a regular expression:
import re
def sep(s, thou=",", dec="."):
integer, decimal = s.split(".")
integer = re.sub(r"B(?=(?:d{3})+$)", thou, integer)
return integer + dec + decimal
sep()
takes the string representation of a standard Python float and returns it with custom thousands and decimal separators.
>>> s = "%.2f" % 32757121.33
>>> sep(s)
'32,757,121.33'
>>> sep(s, thou=".", dec=",")
'32.757.121,33'
Explanation:
B # Assert that we're not at the start of the number
(?= # Match at a position where it's possible to match...
(?: # the following regex:
d{3} # 3 digits
)+ # repeated at least once
$ # until the end of the string
) # (thereby ensuring a number of digits divisible by 3
I have found another solution:
'{:,.2f}'.format(num).replace(".","%").replace(",",".").replace("%",",")
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8')
'en_GB.UTF-8'
>>> print(locale.format_string('%.2f', 12742126.15, True))
12,742,126.15
This sample code works for GB in a docker container.
FROM python:3.8.2-slim-buster
RUN apt-get update && apt-get install -y locales &&
sed -i -e 's/# en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen &&
dpkg-reconfigure --frontend=noninteractive locales
ENV LANG en_GB.UTF-8
ENV LC_ALL en_GB.UTF-8
Locales could be found by running the following command on your terminal (Linux Dirstro)
locale -a
Then a full list of locales appear:
en_AG.utf8
en_AU.utf8
...
en_GB.utf8
...
I liked def sep...
, but it doesn’t change the problem of finding the local format for numbers automatically. That is really what you want if you don’t want to add lots of code to your reporting.
You could use
g.periodsOrCommas={'thou':'.','dec':','}
where g is a globally available area.
change sep to:
def sep(s:str):
thou=g.periodsOrCommas['thou']
dec= g.periodsOrCommas['dec']
Then as part of the program setup, or an inquiry to the user, set periods and commas to the required formats. In all reports or windows, call sep to deal with floating point representation.
Lastly, you could have options in sep to specify the number of decimal places, or even the type of formatting needed. But that is way off the current question.
Thanks for a great solution to an actual problem I was facing.