This question already has answers here:
What class to use for money representation?
(6 answers)
Closed 13 days ago.
This post was edited and submitted for review 13 days ago and failed to reopen the post:
Original close reason(s) were not resolved
I know that Decimal or a custom class is generally is the preferred way of representing currency, but I am asking if it can be also achieved using integer. If not possible, I would like to know why.
I know we should never use float to represent currency, because of the floating point precision issues:
burger = 1.3
amount = 3
total = burger * amount # 3.9000000000000004
Python have the Decimal module that solves the issue:
from decimal import Decimal
burger = Decimal('1.3')
amount = 3
total = burger * amount # Decimal('3.9')
print(total) # 3.9
But there is also the option to store the values and do the Math operations using integers. If we need to show the value to a human, we just divide by 100 to show the representation as currency:
burger = 130
amount = 3
total = burger * amount # 390
print(total / 100) # 3.9
Using integers seem much simpler, but would the integer solution work in any situation involving currency representation? Is there any trade-offs when using integer to represent currency?
trade-offs between using integer or Decimal
With addition/subtraction, it makes little difference.
Consider interest/tax calculations, equated monthly installment, future value etc.
Do you want to use integers to calculate them?
Related
This question already has answers here:
How to get largest possible precision? (Python - Decimal)
(4 answers)
Closed 5 months ago.
I have done some research throughout SO and I believe this is not a duplicate of How to get largest possible precision? (Python - Decimal) or Arithmetic precision problems with large numbers or How to store a big floating point number in python variable?
Let's say that I have this number: 11400361308443875328.123123123123
What data type can I use to store this in Python? I have tried float, decimal and the result it gives me:
x = Decimal('11400361308443875328.123123123123123') + Decimal('11400361308443875328.123123123123123')
print("{:12f}".format(x))
# 22800722616887750656.24624625
y = float(11400361308443875328.123123123123) + float(11400361308443875328.123123123123)
print("{:12f}".format(y))
# 22800722616887750656.000000
z = Decimal('0.123123123123123') + Decimal('0.123123123123123')
print("{:12f}".format(z))
# 0.246246246246246
I need the degree of precision that z has. How should I store this big number with floating precision so that I can do some mathematical operations on it? Is there some trick on how I can do this?
For the question on why I need this high degree of precision: this is a question from a coding challenge (not the actual question), and the submission is graded with a leeway of +- 10^-6 precision
If decimal's default precision is not enough, you can change it by modifying value of getcontext().prec - https://docs.python.org/3/library/decimal.html#module-decimal
from decimal import Decimal, getcontext
getcontext().prec = 50
x = Decimal('11400361308443875328.123123123123123') + Decimal('11400361308443875328.123123123123123123')
print(x) # 22800722616887750656.246246246246246123
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 10 months ago.
In this program, I am asking the user to input two datetime, and I convert the differences between the two date times into several floats. difference_days is one of the float of total difference in days.
so basically, I am writing this in for loop
part of my code is below:
if difference_days.is_integer():
print(f'The difference is {int(difference_days)} days.')
else:
hours = (difference_days - int(difference_days))*24.0
print(int(difference_days))
print(difference_days)
print(difference_days - int(difference_days))
print(hours)
if difference_hours.is_integer():
print(f'The difference is {int(difference_days)} days and {int(hours)} hours.')
else:
... # other codes that handle minutes, seconds, microseconds
I did not post all the codes, because I think there's something wrong with the calculation in python.
so those print statements between hours and the second if statement is just for test, and below is the output:
91
91.95833333333333
0.9583333333333286
22.999999999999886
I was confused why the third one starts to have more decimal places in the end while the second doesn't. How should I fix that? I would like it to only display the 12 decimals.
You can just use the format() function, and convert it to a floating point, like this:
float(format(difference_days,".12f"))
This will return difference_days as a floating point with 12 decimals
Well I guess I just found the solution, so I did the following, but any better ideas?
from decimal import *
getcontext().prec = 12
hours = (Decimal(difference_days) - int(difference_days))*24
Floating points can't be perfectly represented in binary, so you will always have the weird error at the end.
Why are floating point numbers inaccurate?
But you can print the 12 digits of the decimal with:
>>> x = 0.9583333333333286
>>> f'{x:.12f}'
'0.958333333333'
>>> float(f'{x:.12f}')
0.958333333333
This question already has answers here:
How to round a number to significant figures in Python
(26 answers)
Closed 1 year ago.
I want to round numbers so that two numbers are used after the last zero, or decimal if the number is greater than 1. I've looked up the documentation for round, but can't seem to find this feature.
If I use round, it always round to n decimals places regardless.
This is the output I'm looking for:
42.0068 --> 42.01
0.00251 --> 0.0025
420.246 --> 420.25
0.192 -> 0.19
0.00000000128 --> 0.0000000013
The kind of rounding you're asking for isn't a common operation.
In terms of common operations you have two cases (ignoring sign since all your examples are positive):
If the value is less than 1, round to significant figures (eg per the link in #quamrana's comment on the question).
Else (ie the value is at least 1), round to decimal places in the usual way.
Your final code would reasonably be a function with a simple if-else:
def round_special(value):
if value < 1:
return round_to_sf(value, 2)
else:
return round_to_dp(value, 2)
You could try with string manipulation. It's not that elegant, but seems to work. It's up to you to complete this code to handle exceptions..
if number>1:
result = round(number,2)
else:
str_number = str(number)
i = str_number.rfind('0')
result = float(str_number[:i+3])
This question already has answers here:
How to print float to n decimal places including trailing 0s?
(5 answers)
Closed 2 years ago.
It's my first week trying to learn how to code.
Rods is input from user so it can be whatever
miles = round(Rods * 0.003125, 20)
print("Distance in Miles = ", miles)
I need this line of code to print 20 decimals. I thought by adding comma 20 it would do so. I then tried looking re-writing it to format{miles: "20.f"}. (Don't remember exactly how the code went)
Any guidance would be appreciated.
Try this snippet:
miles = Rods * 0.003125
print("Distance in Miles = {:.20f}".format(miles))
This code does the calculation first and formats the answer such that it is displayed in 20 decimal places. For displaying only 10 decimal places change to .10f, for 2 decimal places change to .2f and so on.
When calling round() method on floats, the unnecessary leading decimal zeros are not counted, since the number is the same.
You can convert the number to string, use .split(".") on it to separate the decimal and whole number
example: "3.85".split(".") will return a list whose elements are ["3", "85"] digits = str(num).split(".")
Lets take the second element, decimals decimals = digits[1]
Then you take the length of second element that is decimals and subtract it from 20. This will be the amount of zeros to add. newDecimals = decimals + (20 - len(decimals)) * "0"
Now, use the list from before to form a new number
final = digits[0] + "." + newDecimals
Keep in mind that converting it back to a float will remove those zeros.
Try following source code :
miles = Rods * 0.003125
miles_formatted_float = "{:.20f}".format(miles)
print("Distance in Miles = "+miles_formatted_float)
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