[python] Specifying number of decimal places in Python

When accepting user input with a decimal in Python I'm using:

#will input meal subtotal  
def input_meal():  
    mealPrice = input('Enter the meal subtotal: $')  
    mealPrice = float (mealPrice)  
    return mealPrice  

which returns exactly what is entered - say $43.45
but when using that value to calculate and display tax I'm using:

#will calculate 6% tax  
def calc_tax(mealPrice):  
    tax = mealPrice*.06  
    return tax

which returns a display of $ 2.607 using

mealPrice = input_meal()
tax = calc_tax(mealPrice)
display_data(mealPrice, tax)  

How can I set that to $2.61 instead?
Forgive me, I realize this is basic stuff but they don't call it Intro for nothing...

Thanks!

This question is related to python

The answer is


There's a few ways to do this depending on how you want to hold the value.

You can use basic string formatting, e.g

'Your Meal Price is %.2f' %  mealPrice

You can modify the 2 to whatever precision you need.

However, since you're dealing with money you should look into the decimal module which has a cool method named quantize which is exactly for working with monetary applications. You can use it like so:

from decimal import Decimal, ROUND_DOWN
mealPrice = Decimal(str(mealPrice)).quantize(Decimal('.01'), rounding=ROUND_DOWN)

Note that the rounding attribute is purely optional as well.


This standard library solution likely has not been mentioned because the question is so dated. While these answers may scale to the other use cases beyond currency where differing levels of decimals are required, it seems you need it for currency.

I recommend you use the standard library locale.currency object. It seems to have been created to address this problem of currency representation.

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')

locale.currency(1.23)
>>>'$1.23'
locale.currency(1.53251)
>>>'$1.23'
locale.currency(1)
>>>'$1.00'

locale.currency(mealPrice)

Currency generalizes to other countries as well.


To calculate tax, you could use round (after all, that's what the restaurant does):

def calc_tax(mealPrice):  
    tax = round(mealPrice*.06,2)
    return tax

To display the data, you could use a multi-line string, and the string format method:

def display_data(mealPrice, tax):
    total=round(mealPrice+tax,2)
    print('''\
Your Meal Price is {m:=5.2f}
Tax                {x:=5.2f}
Total              {t:=5.2f}
'''.format(m=mealPrice,x=tax,t=total))

Note the format method was introduced in Python 2.6, for earlier versions you'll need to use old-style string interpolation %:

    print('''\
Your Meal Price is %5.2f
Tax                %5.2f
Total              %5.2f
'''%(mealPrice,tax,total))

Then

mealPrice=input_meal()
tax=calc_tax(mealPrice)
display_data(mealPrice,tax)

yields:

# Enter the meal subtotal: $43.45
# Your Meal Price is 43.45
# Tax                 2.61
# Total              46.06

Use round() function.

round(2.607) = 3
round(2.607,2) = 2.61

I'm astonished by the second number you mention (and confirm by your requested rounding) -- at first I thought my instinct for mental arithmetic was starting to fail me (I am getting older, after all, so that might be going the same way as my once-sharp memory!-)... but then I confirmed it hasn't, yet, by using, as I imagine you are, Python 3.1, and copying and pasting..:

>>> def input_meal():  
...     mealPrice = input('Enter the meal subtotal: $')  
...     mealPrice = float (mealPrice)  
...     return mealPrice  
... 
>>> def calc_tax(mealPrice):  
...     tax = mealPrice*.06  
...     return tax
... 
>>> m = input_meal()
Enter the meal subtotal: $34.45
>>> print(calc_tax(m))
2.067
>>> 

...as expected -- yet, you say it instead "returns a display of $ 2.607"... which might be a typo, just swapping two digits, except that you then ask "How can I set that to $2.61 instead?" so it really seems you truly mean 2.607 (which might be rounded to 2.61 in various ways) and definitely not the arithmetically correct result, 2.067 (which at best might be rounded to 2.07... definitely not to 2.61 as you request).

I imagine you first had the typo occur in transcription, and then mentally computed the desired rounding from the falsified-by-typo 2.607 rather than the actual original result -- is that what happened? It sure managed to confuse me for a while!-)

Anyway, to round a float to two decimal digits, simplest approach is the built-in function round with a second argument of 2:

>>> round(2.067, 2)
2.07
>>> round(2.607, 2)
2.61

For numbers exactly equidistant between two possibilities, it rounds-to-even:

>>> round(2.605, 2)
2.6
>>> round(2.615, 2)
2.62

or, as the docs put it (exemplifying with the single-argument form of round, which rounds to the closest integer):

if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2).

However, for computations on money, I second the recommendation, already given in other answers, to stick with what the decimal module offers, instead of float numbers.


You don't show the code for display_data, but here's what you need to do:

print "$%0.02f" %amount

This is a format specifier for the variable amount.

Since this is beginner topic, I won't get into floating point rounding error, but it's good to be aware that it exists.