user2998454
user2998454

Reputation: 155

Inaccuracies with decimals in Python

The following simple code:

from decimal import getcontext
from decimal import *
import math

context = getcontext()
context.prec = 300    

def f(x):
    return Decimal(math.atan(10**(-x+1)))

def xNext(x,y):
    return x-y*f(2)


def yNext(x,y):
    return y+x*f(2)

x= Decimal(1)
y = Decimal(0)

x=xNext(x,y)
y=yNext(x,y)

x=xNext(x,y)
y=yNext(x,y)

x=xNext(x,y)
y=yNext(x,y)

print("{:.16f}".format(x))
print("{:.16f}".format(y))

returns

0.9702971603146833
0.2950554229911823

Which is wrong, should be around 0.97019857 and 0.2980158649 I thought this was a rounding error but this code should be working to 300 decimal places.

Not sure if different problem or not really going to 300 places...

EDIT: Yeah, I doubt it's a rounding error, I've just done the same process on wolfram only to around 20 decimal places at a time and my answer's more accurate than this one.

Upvotes: 0

Views: 89

Answers (2)

Daniel
Daniel

Reputation: 42758

Decimal doesn't extend your precision, because you use the math module. But that's not the point. Are you sure you calculation is correct? Just tried:

x, y = 1, 0
x, y = xNext(x,y), yNext(x,y)
x, y = xNext(x,y), yNext(x,y)
x, y = xNext(x,y), yNext(x,y)

And it leads to

0.970198479132
0.298015864998

which is basically your expected result.

Upvotes: 2

Tony Suffolk 66
Tony Suffolk 66

Reputation: 9704

I think that the problem lies here :

 return Decimal(math.atan(10**(-x+1)))

I would imagine that ALL of the calculations in that formula (especially the math.atan function) will be calculated as a normal precision floating point number - and then converted back to a 300 decimal point Decimal.

If you want 300 point precision, you MUST find a way to ensure that every calculation is executed to that level of precision or better, as your result will only be as precise as your LEAST precise calculation.

Upvotes: 1

Related Questions