Python 中的小数不准确
Inaccuracies with decimals in Python
下面简单的代码:
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
这是错误的,应该在 0.97019857 和 0.2980158649 左右
我认为这是一个舍入错误,但这段代码应该可以精确到小数点后 300 位。
不确定是否有不同的问题或是否真的要去 300 个地方...
编辑:是的,我怀疑这是一个舍入错误,我刚刚在 wolfram 上完成了相同的过程,一次只保留了大约 20 位小数,我的答案比这个更准确。
我认为问题出在这里:
return Decimal(math.atan(10**(-x+1)))
我认为该公式中的所有计算(尤其是 math.atan 函数)都将计算为普通精度浮点数 - 然后转换回 300 位小数。
如果你想要 300 点的精度,你必须找到一种方法来确保每个计算都执行到该精度或更好的精度,因为你的结果只会与你的 LEAST 精度计算一样精确。
Decimal 不会扩展您的精度,因为您使用了 math
模块。但这不是重点。你确定你的计算是正确的?刚试过:
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)
它导致
0.970198479132
0.298015864998
这基本上是您的预期结果。
下面简单的代码:
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
这是错误的,应该在 0.97019857 和 0.2980158649 左右 我认为这是一个舍入错误,但这段代码应该可以精确到小数点后 300 位。
不确定是否有不同的问题或是否真的要去 300 个地方...
编辑:是的,我怀疑这是一个舍入错误,我刚刚在 wolfram 上完成了相同的过程,一次只保留了大约 20 位小数,我的答案比这个更准确。
我认为问题出在这里:
return Decimal(math.atan(10**(-x+1)))
我认为该公式中的所有计算(尤其是 math.atan 函数)都将计算为普通精度浮点数 - 然后转换回 300 位小数。
如果你想要 300 点的精度,你必须找到一种方法来确保每个计算都执行到该精度或更好的精度,因为你的结果只会与你的 LEAST 精度计算一样精确。
Decimal 不会扩展您的精度,因为您使用了 math
模块。但这不是重点。你确定你的计算是正确的?刚试过:
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)
它导致
0.970198479132
0.298015864998
这基本上是您的预期结果。