Specifying number of decimal places in Python - 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!

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.

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.

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

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.

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.

Use round() function.
round(2.607) = 3
round(2.607,2) = 2.61

Related

Most Pythonic Way To Round a Float After Calculation

Ultimately, I am trying to accomplish the calculation of a number that gives me back 3 decimal places, and round it to 2 decimal places. What I have, is thus:
total = 175
tax = .0875
total += total * tax # giving me my desired total
print total
>>> 190.3125
rounded = round(total, 2) # giving me my desired decimal place
print rounded
>>> 190.31
I was thinking of doing the total and rounded line in one, but it looks jumbled...
Here is what I feel is the fastest way, but does not look as readable as I would like:
total = round((total + (total*tax)), 2)
print total
>>> 190.31
EDIT
Thank you guys for the input in the comments. It seems time is clearly not something to stress here & I am going to run with rounded = round(total, 2) for my code. Thanks again!
I think you should first think pythonically. What is the critical purpose of rounding a float? Do you need to use this rounded float to calculate later or you want to display it? Or you want to store it into a file or database with a consistent format? Different purposes lead to different methods.
If you want to use this rounded float to calculate later, you just don't need to round it. We should not do any additional process before the final calculation as it will only reduce the precision of results without any benefit.
If you want to display this rounded float, you can keep the precision inside variable and use string format: print "%.2f" % total. This will also print out what you want but won't make you lose precision.
If you want to store it into a file or a database, you can just go to rounded = round(total, 2), it is really pythonic and useful.

I need to create a BMI calculator however it does not round to two decimal places. I was wondering how to do so. This is my code so far in python

height = float(input("What is your height in meters?"))
weight = float(input("What is your weight in kg?"))
sum = weight/height/height
print('The sum is {0} divided by {1} divided by {1} equals {2}'.format(weight,height,sum))
Life will be easier for you, as a programmer, if you use google. And I mean no offence. In this case, just query for python round.
In this particular case, if you want to round a float called BMD to two decimal places then you would use the following expression,
round(BMD,2)
You might also be interested in how to use formatting to achieve a similar result. First I deliberately set BMD to a value that has only two decimal places. I can print it as-is but I have no control. In the second case, I set BMD to a value for quite a few decimal places but this time I limit the number of output decimal places.
In my opinion, it's safer to use round and then use the first formatting option because the second option could stumble with a value such as 345.22 (which occupies more than four columns overall).
>>> BMD = 5.21
>>> print ('BMD is {}'.format(BMD))
BMD is 5.21
>>> BMD = 5.213333333333333
>>> print ('BMD is {:4.2f}'.format(BMD))
BMD is 5.21

float rounding problems in python

amount = 0.002638309660058967
price = 1392.18
lowest_ask = 1391.6
result = price*amount/lowest_ask
print(result)
The above code will print out:
0.002639409271731024
However when I perform the calculation here: http://web2.0calc.com/
It gives me: 0.0026394092717310237698
So obviously python is rounding up the result of this calculation....
My question is, how do you prevent python from rounding up result? i.e. I want result to be: 0.002639409271731023
Python is using IEEE 64-bit floating point to do the calculations. You can get it to print out as many digits as you want, but that later digits won't be meaningful since there is only so much that can be represented in 64-bits.
>>> print "{0:.30f}".format(result)
0.002639409271731024079349348099
If you want more digits of precision, then you won't be able to use the float type. In that case you can use the decimal module, but the calculations will be much slower.
If you do go down the path of using the decimal module, then here's the code with the default 28 digits of precision:
from decimal import *
amount = Decimal('0.002638309660058967')
price = Decimal('1392.18')
lowest_ask = Decimal('1391.6')
result = price*amount/lowest_ask
print(result)
0.002639409271731023769804541535
Since your example is related to small financial operations, the decimal module is a good choice (see previous answer). For scientific computation with high emphasis on speed, you could use some arbitrary-precision module like gmpy:
from gmpy import mpf
amount = mpf('0.002638309660058967')
price = mpf('1392.18')
lowest_ask = mpf('1391.6')
result = price*amount/lowest_ask
print(result)
0.0026394092717310237698
(of course you can use as many digits as wanted). For computing with a fixed amount of precision ~32 or ~64 decimal digits, the module qd is also a good choice.

rounding float up $.01 in python

I am working on a program that stores numbers as floats which I eventually write to a file as currency. I am currently using the round() function to round it to 2 decimals, but the business area would like me to round to the next penny no matter what the third decimal is. For example:
x = 39.142
In this case I am trying to get x to round up to 39.15. Obviously when I do the round function I get 39.14...
>>> round(x, 2)
39.14
Is there a way I can always round up to the next penny? I should mention that the numbers I am dealing with are printed to the file as currency.
Using the decimal module:
import decimal
D = decimal.Decimal
cent = D('0.01')
x = D('39.142')
print(x.quantize(cent,rounding=decimal.ROUND_UP))
# 39.15
Decimals have many options for rounding. The options and their meanings can be found here.
if you want to write it in cents, you could use int(x*100+.5) to get cents integer from float dollars.
Very late to this, but in case anyone wants a simple one-liner in Python 3:
import math
x_rounded = math.ceil(x*100) / 100

Doing arithmetic with up to two decimal places in Python?

I have two floats in Python that I'd like to subtract, i.e.
v1 = float(value1)
v2 = float(value2)
diff = v1 - v2
I want "diff" to be computed up to two decimal places, that is compute it using %.2f of v1 and %.2f of v2. How can I do this? I know how to print v1 and v2 up to two decimals, but not how to do arithmetic like that.
The particular issue I am trying to avoid is this. Suppose that:
v1 = 0.982769777778
v2 = 0.985980444444
diff = v1 - v2
and then I print to file the following:
myfile.write("%.2f\t%.2f\t%.2f\n" %(v1, v2, diff))
then I will get the output: 0.98 0.99 0.00, suggesting that there's no difference between v1 and v2, even though the printed result suggests there's a 0.01 difference. How can I get around this?
thanks.
You said in a comment that you don't want to use decimal, but it sounds like that's what you really should use here. Note that it isn't an "extra library", in that it is provided by default with Python since v2.4, you just need to import decimal. When you want to display the values you can use Decimal.quantize to round the numbers to 2 decimal places for display purposes, and then take the difference of the resulting decimals.
>>> v1 = 0.982769777778
>>> v2 = 0.985980444444
>>> from decimal import Decimal
>>> d1 = Decimal(str(v1)).quantize(Decimal('0.01'))
>>> d2 = Decimal(str(v2)).quantize(Decimal('0.01'))
>>> diff = d2 - d1
>>> print d1, d2, diff
0.98 0.99 0.01
I find round is a good alternative.
a = 2.000006
b = 7.45001
c = b - a
print(c) #This gives 5.450004
print(round(c, 2)) ##This gives 5.45
I've used poor man's fixed point in the past. Essentially, use ints, multiply all of your numbers by 100 and then divide them by 100 before you print.
There was a good post on similar issues on Slashdot recently.
The thing about the float type is that you can't really control what precision calculations are done with. The float type is letting the hardware do the calculations, and that typically does them the way it's most efficient. Because floats are (like most machine-optimized things) binary, and not decimal, it's not straightforward (or efficient) to force these calculations to be of a particular precision in decimal. For a fairly on-point explanation, see the last chapter of the Python tutorial. The best you can do with floats is round the result of calculations (preferably just when formatting them.)
For controlling the actual calculations and precision (in decimal notation, no less), you should consider using Decimals from the decimal module instead. It gives you much more control over pretty much everything, although it does so at a speed cost.
What do you mean "two significant figures"? Python float has about 15 sigfigs, but it does have representation errors and roundoff errors (as does decimal.Decimal.) http://docs.python.org/tutorial/floatingpoint.html might prove an interesting read for you, along with the great amount of resources out there about floating point numbers.
float usually has the right kind of precision for representing real numbers, such as physical measurements: weights, distances, durations, temperatures, etc. If you want to print out a certain way of displaying floats, use the string formatting as you suggest.
If you want to represent fixed-precision things exactly, you probably want to use ints. You'll have to keep track of the decimal place yourself, but this is often not too tough.
decimal.Decimal is recommended way too much. It can be tuned to specific, higher-than-float precision, but this is very seldom needed; I don't think I've ever seen a problem where this was the reason someone should use decimal.Decimal. decimal.Decimal lets you represent decimal numbers exactly and control how rounding works, which makes it suitable for representing money in some contexts.
You could format it using a different format string. Try '%.2g' or '%.2e'. Any decent C/C++ reference will describe the different specifiers. %.2e formats the value to three significant digits in exponential notation - the 2 means two digits following the decimal point and one digit preceding it. %.2g will result in either %.2f or %.2e depending on which will yield two significant digits in the minimal amount of space.
>>> v1 = 0.982769777778
>>> v2 = 0.985980444444
>>> print '%.2f' %v1
0.98
>>> print '%.2g' %v1
0.98
>>> print '%.2e' %v1
9.83e-01
>>> print '%.2g' %(v2-v1)
0.0032
>>> print '%.2e' %(v2-v1)
3.21e-03

Categories