Question :
I want to display:
49
as 49.00
and:
54.9
as 54.90
Regardless of the length of the decimal or whether there are are any decimal places, I would like to display a Decimal
with 2 decimal places, and I’d like to do it in an efficient way. The purpose is to display money values.
eg, 4898489.00
Answer #1:
I suppose you’re probably using the Decimal()
objects from the decimal
module? (If you need exactly two digits of precision beyond the decimal point with arbitrarily large numbers, you definitely should be, and that’s what your question’s title suggests…)
If so, the Decimal FAQ section of the docs has a question/answer pair which may be useful for you:
Q. In a fixed-point application with two decimal places, some inputs have many places and need to be rounded. Others are not supposed to have excess digits and need to be validated. What methods should be used?
A. The quantize() method rounds to a fixed number of decimal places. If the Inexact trap is set, it is also useful for validation:
>>> TWOPLACES = Decimal(10) ** -2 # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
...
Inexact: None
The next question reads
Q. Once I have valid two place inputs, how do I maintain that invariant throughout an application?
If you need the answer to that (along with lots of other useful information), see the aforementioned section of the docs. Also, if you keep your Decimal
s with two digits of precision beyond the decimal point (meaning as much precision as is necessary to keep all digits to the left of the decimal point and two to the right of it and no more…), then converting them to strings with str
will work fine:
str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'
Answer #2:
You should use the new format specifications to define how your value should be represented:
>>> from math import pi # pi ~ 3.141592653589793
>>> '{0:.2f}'.format(pi)
'3.14'
The documentation can be a bit obtuse at times, so I recommend the following, easier readable references:
- the Python String Format Cookbook: shows examples of the new-style
.format()
string formatting - pyformat.info: compares the old-style
%
string formatting with the new-style.format()
string formatting
Python 3.6 introduced literal string interpolation (also known as f-strings) so now you can write the above even more succinct as:
>>> f'{pi:.2f}'
'3.14'
Answer #3:
The String Formatting Operations section of the Python documentation contains the answer you’re looking for. In short:
"%0.2f" % (num,)
Some examples:
>>> "%0.2f" % 10
'10.00'
>>> "%0.2f" % 1000
'1000.00'
>>> "%0.2f" % 10.1
'10.10'
>>> "%0.2f" % 10.120
'10.12'
>>> "%0.2f" % 10.126
'10.13'
Answer #4:
You can use the string formatting operator as so:
num = 49
x = "%.2f" % num # x is now the string "49.00"
I’m not sure what you mean by “efficient” — this is almost certainly not the bottleneck of your application. If your program is running slowly, profile it first to find the hot spots, and then optimize those.
Answer #5:
>>> print "{:.2f}".format(1.123456)
1.12
You can change 2
in 2f
to any number of decimal points you want to show.
EDIT:
From Python3.6
, this translates to:
>>> print(f"{1.1234:.2f}")
1.12
Answer #6:
In python 3, a way of doing this would be
'{:.2f}'.format(number)
Answer #7:
.format is a more readable way to handle variable formatting:
'{:.{prec}f}'.format(26.034, prec=2)
Answer #8:
if you have multiple parameters you can use
print('some string {0:.2f} & {1:.2f}'.format(1.1234,2.345))
>>> some string 1.12 & 2.35