Jesvin Jose
Jesvin Jose

Reputation: 23098

Can I safely use int in Decimal calculations in Python?

I have used "decimal" constants, just in case. Could I rather use integers for the same purpose safely, like integer 0 and 1 here? Its for storing money.

    if SOMETHING:
        invoice.tax_rate = Decimal(TAXRATE_STRING)
    else:
        invoice.tax_rate = Decimal("0.00")
    invoice.total_amount =\
        invoice.pretax_amount * (Decimal("1") + invoice.tax_rate)

Upvotes: 0

Views: 144

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1123360

Yes, you can safely use integers; they'll be coerced to Decimal objects as required.

The Decimal class implements many of the numeric emulation hooks to do so, including the __r*__ variants to ensure that this works even if the integer is the left-hand operand.

For your specific case, if the tax rate was set to integer 0 and you used an integer 1, you'd get:

>>> from decimal import Decimal
>>> Decimal('20.00') * (1 + 0)
Decimal('20.00')

The summing of the tax rate results in a Decimal object if it is not set to integer 0:

>>> 1 + Decimal('0.20')
Decimal('1.20')

etc.

Internally, the decimal._convert_other() function is used to handle the coercion. It'll convert integers and long integers to Decimal() always, floats only when explicitly instructed to (only for rich comparisons, so == and <=, etc.), the rest is explicitly rejected. Floats are not suited for automatic conversion; it is too easy to introduce bugs in your code if you allowed for floats to be converted implicitly.

Upvotes: 1

NPE
NPE

Reputation: 500663

Yes you can, for example:

In [8]: d = decimal.Decimal("123.45")

In [9]: d / 10
Out[9]: Decimal('12.345')

Note that this does not work with floating-point values:

In [10]: d / 123.45
TypeError: unsupported operand type(s) for /: 'Decimal' and 'float'

I would argue that this is good news, because implicitly mixing Decimal and float would be too error-prone.

Upvotes: 1

Related Questions