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
For the analogous issue with the built-in float type, see Limiting floats to two decimal points.
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'
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'
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 Decimals 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'
>>> 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
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.
.format is a more readable way to handle variable formatting:
'{:.{prec}f}'.format(26.034, prec=2)
In python 3, a way of doing this would be
'{:.2f}'.format(number)
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
The OP always wants two decimal places displayed, so explicitly calling a formatting function, as all the other answers have done, is not good enough.
As others have already pointed out, Decimal works well for currency. But Decimal shows all the decimal places. So, override its display formatter:
class D(decimal.Decimal):
def __str__(self):
return f'{self:.2f}'
Usage:
>>> cash = D(300000.991)
>>> print(cash)
300000.99
Simple.
EDIT:
To display at least two decimal places but without truncating significant digits:
class D(decimal.Decimal):
def __str__(self):
"""Display at least two decimal places."""
result = str(self)
i = result.find('.')
if i == -1:
# No '.' in self. Pad with '.00'.
result += '.00'
elif len(result[i:]) == 2:
# One digit after the decimal place. Pad with a '0'.
result += '0'
return result
I hope that a future version of Python will improve the number formatting to allow minimum decimal places. Something like the # sign in Excel's number formatting.
If you're using this for currency, and also want the value to be seperated by ,'s you can use
$ {:,.f2}.format(currency_value).
e.g.:
currency_value = 1234.50
$ {:,.f2}.format(currency_value) --> $ 1,234.50
Here is a bit of code I wrote some time ago:
print("> At the end of year " + year_string + " total paid is \t$ {:,.2f}".format(total_paid))
> At the end of year 1 total paid is $ 43,806.36
> At the end of year 2 total paid is $ 87,612.72
> At the end of year 3 total paid is $ 131,419.08
> At the end of year 4 total paid is $ 175,225.44
> At the end of year 5 total paid is $ 219,031.80 <-- Note .80 and not .8
> At the end of year 6 total paid is $ 262,838.16
> At the end of year 7 total paid is $ 306,644.52
> At the end of year 8 total paid is $ 350,450.88
> At the end of year 9 total paid is $ 394,257.24
> At the end of year 10 total paid is $ 438,063.60 <-- Note .60 and not .6
> At the end of year 11 total paid is $ 481,869.96
> At the end of year 12 total paid is $ 525,676.32
> At the end of year 13 total paid is $ 569,482.68
> At the end of year 14 total paid is $ 613,289.04
> At the end of year 15 total paid is $ 657,095.40 <-- Note .40 and not .4
> At the end of year 16 total paid is $ 700,901.76
> At the end of year 17 total paid is $ 744,708.12
> At the end of year 18 total paid is $ 788,514.48
> At the end of year 19 total paid is $ 832,320.84
> At the end of year 20 total paid is $ 876,127.20 <-- Note .20 and not .2
This is the same solution as you have probably seen already, but by doing it this way it's more clearer:
>>> num = 3.141592654
>>> print(f"Number: {num:.2f}")
The Easiest way example to show you how to do that is :
Code :
>>> points = 19.5
>>> total = 22
>>>'Correct answers: {:.2%}'.format(points/total)
`
Output : Correct answers: 88.64%
what about
print round(20.2564567 , 2) >>>>>>> 20.25
print round(20.2564567 , 4) >>>>>>> 20.2564
Hi I am python beginner!
Here is the questions I am having problem with!
Question:
Write a program to prompt the user for hours and rate per hour using raw_input to compute gross pay. Pay the hourly rate for the hours up to 40 and 1.5 times the hourly rate for all hours worked above 40 hours. Use 45 hours and a rate of 10.50 per hour to test the program (the pay should be 498.75). You should use raw_input to read a string and float() to convert the string to a number. Do not worry about error checking the user input - assume the user types numbers properly.
My answer was below but can't get 498.75, and I am not too sure where it went wrong.
Please help :)
hrs = raw_input('Enter hours ')
h= float(hrs) #why use float?
rate = float(10.5)
if h <= 40:
pay = h*rate
elif h > 40:
pay = ((h-40)*rate*1.5)+rate*40
print "Your pay is %d" %pay
Your code is correct, but you are using %d to print the value of variable pay, which converts it back to int and the decimal part is ignored.
So try using %s or %f or %.2f.
Your calculation is correct, you just need to format the output correctly. %d is for integers so changing to %f which is used for floats will do the trick:
print "Your pay is %f" %pay
With above change you'll get following output:
Your pay is 498.750000
You can find the full list of different format specifiers from Python docs.
When you print the pay of the user, you use %d to print the actual pay. To display floating point numbers (such as 498.75), you have to use %f (or more precisely, %.2f since you can't pay someone less than 1 cent).
So this would be the correct way, that wields 498.75 :
hrs = raw_input('Enter hours ')
h= float(hrs) #why use float?
rate = float(10.5)
if h <= 40:
pay = h*rate
elif h > 40:
pay = ((h-40)*rate*1.5)+rate*40
print "Your pay is %.2f" %pay
You can find more informations regarding string formatting here
Also, regarding the h= float(hrs) #why use float? :
by default, raw_input() returns a string, you have to use float() to parse this string to a floating point number, and to use it in your computation later on.
Hope it'll be helpful.
I am attempting to teach myself a little coding through the "learn python the hard way" book and am struggling with %d / %s / %r when tying to display a floating point number. How do you properly pass a floating point number with a format character? First I tried %d but that made my answers display as integers.... I had some success with %r, but I was under the assumption that was usually reserved for debugging? I figured out for division in python 2.x you have to manually float the denominator for it to properly work for some reason.
Example code:
def divide (a, b):
print "WE DIVIDING %r and %r NOW" % (a, b)
return a / float(b)
print "Input first number:"
first = float(raw_input("> "))
print "OK, now input second number:"
second = float(raw_input("> "))
ans = divide(first, second)
print "DONE: %r DIVIDED BY %r EQUALS %r, SWEET MATH BRO!" % (first, second, ans)
See String Formatting Operations:
%d is the format code for an integer. %f is the format code for a float.
%s prints the str() of an object (What you see when you print(object)).
%r prints the repr() of an object (What you see when you print(repr(object)).
For a float %s, %r and %f all display the same value, but that isn't the case for all objects. The other fields of a format specifier work differently as well:
>>> print('%10.2s' % 1.123) # print as string, truncate to 2 characters in a 10-place field.
1.
>>> print('%10.2f' % 1.123) # print as float, round to 2 decimal places in a 10-place field.
1.12
Try the following:
print "First is: %f" % (first)
print "Second is: %f" % (second)
I am unsure what answer is. But apart from that, this will be:
print "DONE: %f DIVIDED BY %f EQUALS %f, SWEET MATH BRO!" % (first, second, ans)
There's a lot of text on Format String Specifiers. You can google it and get a list of specifiers. One thing I forgot to note:
If you try this:
print "First is: %s" % (first)
It converts the float value in first to a string. So that would work as well.
I'm making a unit converter just to practice. Currently, I've defined a function to figure out what type of conversion to make (distance, time, mass, etc.).
It then calls the correct converter for the type, asks what you're converting from, what you're converting to, and what the value for conversion is.
def mass_converter():
convert_from = raw_input('What unit are you converting from? ')
convert_to = raw_input('What unit are you converting to? ')
value = raw_input('How many of those do you have? ')
if convert_from == "pounds" and convert_to == "kilograms":
answer = float(value) * 0.453592
print "That many pounds is %d kilograms." % answer
elif convert_from == "kilograms" and convert_to == "pounds":
answer = float(value) * 2.20462
print "That many kilograms is %d pounds." % answer
else:
print "You have not selected a valid unit; please try again."
mass_converter()
Currently, if I were to convert 10 pounds to kilograms, it tells me that the answer is 4 kilograms. It seems to be chopping off my decimals. Obviously int(value) will do the same thing. What can I use to keep the exact value entered by the user?
The problem here is that you're using the %d format modifier in your string formatting which casts your answer to an integer. Use %f instead (or even %s).
You could use %f instead of %d. %d formats the number not as a floating point, but as a integer. Alternatively you could use
print "That many kilograms is {} pounds.".format(answer)
In the round function, what means the number 2 as the second argument?
##This is a program that calcs your credit card, and compounds down the total
a=float(raw_input("Enter the outstanding balance on your credit card:"))
b=float(raw_input("Enter the annual crdit card interest rate as a deicimal:"))
c=float(raw_input("Enter the minimum monthly payment as a decimal:"))
for month in range(1, 13):
print "Month: ", str(month)
MMP = round((c * a),2) ##the 2 here and below, what does it do?
print "Minimum monthly payment: ", MMP
IP = round((b/12 * a),2)
print "Interest payed: ", IP
PP = round(((c*a) - ((b/12)*a)),2)
print "principal payed: ", PP
a = round((a - PP),2)
print "Remaining balance", a
The 2 is passed as the second argument to round, giving the number of decimal places to round to. This will round it to the nearest float representing the number rounded to two decimal places. Note that this is a very bad idea and a common source of bugs. Use a fractions.Fraction or decimal.Decimal instead.
Floats should never be used for money, especially when you're rounding them like this.
2 is the quantity of decimal digits to use in the rounding operation. Take a look here: http://docs.python.org/library/functions.html#round
This rounds a number so that after the operation it has 2 decimal digits.
Check the docs below:
http://docs.python.org/library/functions.html#round