Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying number of decimal places in Python

Tags:

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!

like image 438
Janet Avatar asked Jul 11 '10 02:07

Janet


2 Answers

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.

like image 99
Bartek Avatar answered Oct 02 '22 19:10

Bartek


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.

like image 35
Alex Martelli Avatar answered Oct 02 '22 18:10

Alex Martelli