DisplayName212
DisplayName212

Reputation: 1

Precision with multiplication in Python's Decimal module

I was using Python's Decimal module to perform multiplication and division under the impression that it would be exact (a/b*b should return a). However, this is not the case.

from decimal import *
getcontext().prec = 50

dec1 = Decimal("703")
dec2 = Decimal("3499")
dec3 = dec1/dec2

print(dec3*dec2)

if dec1==dec3*dec2:
    print(True)
else:
    print(False)

The output I got is

702.99999999999999999999999999999999999999999999999
False

My question is is there any module or function to make this process more exact? I have code that require this relation (a/b*b ==a) to be true.

Upvotes: 0

Views: 244

Answers (3)

codeblooded
codeblooded

Reputation: 350

When using real numbers, it is always recommended to not use ==. The division leads to a real number which has a fixed memory (varies on the language), thus the division is always rounded off. Thereby causing the multiplication to give an approximate answer.

Instead you can use,

def check_equals(a, b, threshold=1e-6):
    if abs(a-b)<threshold:
        return True
    return False

You can change the threshold to your liking.

Upvotes: 1

kaya3
kaya3

Reputation: 51037

The Decimal class is meant for representing decimal numbers with a fixed number of decimal places. This means that most fractions will not be represented exactly, since they have infinite decimal expansions; for example, 1/3 = 0.333333333... will be rounded to a finite number of decimal places as a Decimal.

If you need exact representations of rational numbers so that multiplication and division are true inverses, use the fractions module:

>>> from fractions import Fraction
>>> a = Fraction(703)
>>> b = Fraction(3499)
>>> c = a / b
>>> print(c)
703/3499
>>> print(c * b)
703
>>> a == c * b
True
>>> d = Fraction(1, 3)
>>> d * 3 == 1
True

Upvotes: 2

Jacob Helfman
Jacob Helfman

Reputation: 151

Consider not using that decimal module for the integers. Per the documentation, the decimal module retains significant figures, including zeros: https://docs.python.org/3/library/decimal.html. You should avoid applying this decimal module to your integers and fractions.

Upvotes: 0

Related Questions