StackOverflow有很多关于浮点表示的主题,关于异常、截断、精度问题。我一直想解释这个问题,但还是没弄明白。在
from operator import add, sub, mul, div
fun = 'add(add(sub(sub(safeDiv(xL1, add(D, mul(sub(add(sub(A, 0), mul(D, rv)), mul(xL1, add(D, 3))), xL1))), add(0, rv)), safeDiv(mul(sub(D, sigma2), safeDiv(sub(safeDiv(xL1, A), 1), add(safeDiv(safeDiv(B1, xL1), sub(4, xL2)), add(sigma1, xL1)))), sigma1)), add(4, B1)), add(add(A, A), sub(add(xL1, xL1), mul(xL2, safeDiv(xL1, add(sub(add(mul(D, -4), add(add(safeDiv(mul(sigma2, sigma2), safeDiv(B1, sigma1)), sub(add(D, safeDiv(xL2, B1)), D)), sub(4, B1))), A), add(mul(sigma2, xL1), mul(xL1, mul(rv, xL2)))))))))'
d = [(
51.696521954140991,
31.156112806482234,
54.629863633907163,
27.491618858013698,
26.223584534107289,
77.10005191617563,
2708.4145268939428,
0.20952943771134946,
15.558278150405643,
102.0,
225.0)]
arglabels = ['xL1', 'sigma1', 'xL2', 'sigma2', 'A', 'B1', 'D', 'rv']
other = {'add': add, 'sub':sub, 'mul':mul,'safeDiv':div}
inputs = dict(zip(arglabels, d[0][: -4] + (d[0][-3]*d[0][-4],)))
inputs.update(other)
print eval(fun, inputs)
此代码应生成225到240之间的结果,但返回一个负数。就这样,没有例外,没有警告,什么都没有。所以一定是某个地方的精度误差,导致结果完全关闭。在
通过舍入最大值,我可以得到一个合理的结果是小数点后1位(这让我接近207…),在某些情况下,numpy的longdubles有帮助,但还不够。我是手工做的(精度损失很大,得到了240)。在
另一个细节是,与主脚本一起在笔记本中运行this behaviour:
当我第一次添加locals字典时,它返回了一个非常合理的结果,但接下来的时间它又回到了负值。一定有什么东西影响这件事,但我也找不到。在
我该怎么做才能避免这种情况?如何生成某种警告?我怎样才能追踪到哪里出了问题?在
编辑:接受的答案可以正确识别问题,请查看答案下方的注释以了解更多详细信息。但是,它没有讨论如何避免它或更正函数。也许这应该是对MathOverflow的讨论。。。在
如果预期结果在
225...240
范围内,则可能出现以下问题:fun
时出错d
中的值不正确add
、sub
、mul
和safeDiv
应该做一些比浮点加法、减法、乘法和除法更复杂的事情。在问题中提供的输入不能给出
-2786.17215265
之外的任何内容,因为这是一个完美的数值结果。没有浮点舍入错误或溢出。下面是测试脚本的输出,其中包含详细版本的算术函数,所有浮点运算都定义良好。没有任何东西可以引起明显的舍入误差。当减去接近值时,存在一些风险操作:然而,这远不是舍入误差。在
同样的结果可以通过C程序或数学工具(MATLAB/Octave)得到。在
屏幕截图中的不同输出是由于没有显示的局部变量的值造成的。由于}相同。局部变量用于输出
Out[108]
与Out[110]
相同,我假设ds
与{Out[109]
和Out[110]
,因此差异在于rv
的值,因为在In[110]
中只有该变量被更改。如果所有其他变量的值都是固定的,那么可以看到如果rv
等于下列值之一,则可以得到Out[109]
(230.62977145178198
),即4.075164147
,4.485709922
,51.72476610
。下面测试脚本中的最后一行输出也说明了这一点。在注意,如果})。所以,从技术上讲,这个函数可以给出从负无穷到正无穷的结果。在
fun
被分析为rv
的函数,它有两个极点(围绕3.3
和{^{pr2}$
当我尝试你的例子时,我得到的答案是:
如果我使用
^{pr2}$gmpy2
并将精度设置为200位,将指数范围设置为~1E9,则得到的答案是:函数似乎返回了一个稳定的结果。所以这个函数可能有问题。在
我会按照@Prune的建议,将复杂的函数分解成更小的步骤。在
相关问题 更多 >
编程相关推荐