How can I format a decimal number so that 32757121.33 will display as 32.757.121,33?
Asked
Active
Viewed 2.1k times
24
Tim Pietzcker
- 313,408
- 56
- 485
- 544
yital9
- 6,254
- 15
- 38
- 51
-
10@AshwiniChaudhary In Germany, the original posters format is normal. – Jonas Schäfer Oct 26 '12 at 07:32
4 Answers
26
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
Tim Pietzcker
- 313,408
- 56
- 485
- 544
-
2With the extra pain that these calls depend on the locales available for the O.S. - furthermore, locale names wll vary across different O.S. and even different Linux distributions (meaning you have to test this on your production server, or have code which provides fallbacks until it find an existing locale) – jsbueno Oct 26 '12 at 12:04
-
1@jsbueno: Good point. The docs also point out that `setlocale()` is not threadsafe and has several other problems, especially when used in larger, multi-module programs, so it's important to read the docs. In a small program, this arguably won't matter that much. Also, there are other locale names like `en_EN` or `de_DE` that might be more universal than `German` etc.; I haven't found a list of allowed locale settings yet, though. – Tim Pietzcker Oct 26 '12 at 12:32
-
so i have such a problem, that : "Caught Error while rendering: unsupported locale setti" i have tried different variants (German, german, de_DE and others). can i do it without locale ? with inly format? – yital9 Oct 26 '12 at 14:34
-
-
1The problem is that it's not thread-safe and assumes that the developer wants the same effect everywhere in the program (unless it's okay to switch constantly back and forth, which is hacky and disgusting). There should be a way to get a value formatted in a given locale without having to set the entire runtime platform to that locale. Like, locale.format(format_string, value, locale) - alas, these seems to be none. – Teekin Jul 03 '17 at 15:20
19
I have found another solution:
'{:,.2f}'.format(num).replace(".","%").replace(",",".").replace("%",",")
Tim Pietzcker
- 313,408
- 56
- 485
- 544
yital9
- 6,254
- 15
- 38
- 51
-
4Horrible solution. What if this gets called on thousands of strings with arbitrary lengths? – Daniel Feb 20 '18 at 07:17
-
4
-
-
1Yeh, it's bad and I'm smiling now looking at that. But it worked back in 2012 :D – yital9 Oct 23 '20 at 08:45
8
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
Tim Pietzcker
- 313,408
- 56
- 485
- 544
-
1thanks a lot! if you are interested in, i have also found this variant '{:20,.2f}'.format(num).replace(".","%").replace(",",".").replace("%",",") – yital9 Oct 26 '12 at 15:22
-
Why create Explanation section when you could just use [verbose](https://docs.python.org/2/library/re.html#re.VERBOSE). – Daniel Feb 20 '18 at 07:19
0
>>> 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
...
Daedalus
- 287
- 2
- 15