tylerl
tylerl

Reputation: 30857

Floats, Decimals, Prices, and partial quantities

While the problem in this particular instance deals with Django and Python, I imagine this problem has shown up elsewhere as well.

Float values have a precision problem, and when used for currency can sometimes lead to inaccuracies, so fixed-precision Decimal is the storage type of choice in most instances.

But what about the case where a price is combined with non-integer quantity, such as in an invoice or receipt. Say Fairy Dust costs $19.99 per gram, and a customer buys 3.5 grams of the stuff. The price is Decimal, while the quantity is a float.

The total then is Decimal(19.99) * float(3.5). But multiplying floats and Decimals isn't allowed:

>>> from decimal import *
>>> Decimal(19.99) * float(3.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'Decimal' and 'float'

Of course, we could cast the price to a float first, but then we lose any advantage we otherwise would have gained by storing the value as a decimal. Or we could store the quantity as a decimal, but that would mean arbitrarily picking a range and precision for the quantity. But at design time, the developer wouldn't necessarily know what range/precision would be necessary for the quantity (which is why floating point numbers exist). Is there a better way?

I'm sure this problem has been solved before; what is the optimal way to go about this type of calculation?

Upvotes: 1

Views: 1829

Answers (1)

karthikr
karthikr

Reputation: 99640

You can convert float to decimal like this:

Decimal(str(float(3.5)))

as a workaround.

One more reason to use float is this intersting benchmarking article

Upvotes: 5

Related Questions