Reputation: 43
I tried to compute the following by setting getcontext().prec = 800
.
>>> from decimal import *
>>> getcontext().prec = 800
>>> Decimal(22.0) / Decimal ( 10.0) - Decimal ( 0.2 )
Decimal('1.999999999999999988897769753748434595763683319091796875')
>>>
But the expected result is 2
. Where am I doing wrong?
Upvotes: 3
Views: 1496
Reputation: 111389
Pass strings to the Decimal constructor instead of floats: Decimal('0.2')
gives the result you expect, Decimal(0.2)
doesn't.
This is because:
If value is a float, the binary floating point value is losslessly converted to its exact decimal equivalent. This conversion can often require 53 or more digits of precision. For example, Decimal(float('1.1')) converts to Decimal('1.100000000000000088817841970012523233890533447265625').
https://docs.python.org/3/library/decimal.html#decimal.Decimal
Upvotes: 3
Reputation: 978
When you construct a Decimal from a floating-point number, you get the exact value of the floating-point number, which may not precisely match the decimal value because that's how floating-point numbers work.
If you want to do precise decimal arithmetic, construct your Decimal objects from strings instead of floating-point numbers:
>>> Decimal('22.0') / Decimal('10.0') - Decimal('0.2')
Decimal('2.0')
Upvotes: 5
Reputation: 5835
It seems that you have to give numbers as a string to prevent them from being evaluated as floating point.
from decimal import *
getcontext().prec = 800
print(Decimal(0.2))
print(Decimal('0.2'))
print(Decimal('22.0') / Decimal ('10.0') - Decimal ('0.2' ))
which gives
0.200000000000000011102230246251565404236316680908203125
0.2
2.0
Upvotes: 1
Reputation: 847
The prec
attribute defines how many numbers after the decimal point will round your number. For example, if you expect 2.00
, its value should be 3
. Or if you want to round the number so that it has no decimal places you can use 1
as a parameter.
from decimal import *
getcontext().prec = 1
print(Decimal(22.0) / Decimal ( 10.0) - Decimal ( 0.2 ))
>> 2
Upvotes: 0