我遇到了Mathematica 8中的一个错误。我在网上找不到任何与之相关的内容,但我承认我不确定要搜索什么。
如果我运行此声明:
0.05 + .10 /. {0.15 -> "pass"}
1.04 + .10 /. {1.14 -> "pass"}
1.05 + .10 /. {1.15 -> "pass"}
1.15 /. {1.15 -> "pass"}
我得到了这个输出:
pass
pass
1.15
pass
我只是忽略了什么?
编辑:在阅读下面的有用讨论后,我将调度表更改为使用了哪个语句:
f[x_] := Which[x == 1.05, -1.709847, x == 1.10, -1.373823,
x == 1.15, -1.119214, x == 1.20, -0.9160143, x == 1.25, -0.7470223, x == 1.30, -0.6015966]
这似乎可以解决问题。
答案 0 :(得分:14)
欢迎来到机器精度的世界。如果你仔细研究1.05 + 10和1.15,你会发现它们不完全相同:
1.05 + .10 // FullForm
==> 1.1500000000000001`
1.15 // FullForm
==> 1.15`
答案 1 :(得分:6)
除了在使用MachinePrecision
时产生小错误外,相同的浮点计算在一天中的不同时间会产生稍微不同的结果。这不是一个错误,而是现代硬件浮点架构如何工作的by-product
这意味着您不应使用ReplaceAll
之类的操作,这些操作取决于对MachinePrecision
数字的确切值的了解。使用==
(和===
)可能没问题,因为它们会忽略MachinePrecision
个数字的最后7个(分别为1个)二进制数字。
使用Mathematica算法应该给出精确的结果,无论何时,您可以将它用于您的示例,如下(10位有效数字)
0.05`10 + .10`10 /. {0.15`10 -> "pass"}
1.04`10 + .10`10 /. {1.14`10 -> "pass"}
1.05`10 + .10`10 /. {1.15`10 -> "pass"}
1.15`10 /. {1.15`10 -> "pass"}
更新:What Every Computer Scientist Should Know About Floating-Point Arithmetic提供了有关浮点运算的更多注意事项。例如,第80页给出了IEEE 754的不同实现如何给出略微不同的结果的示例,即使是符合标准的
答案 2 :(得分:4)
您的替换只适用于完全匹配,而您的While语句使用Equal
。您也可以使用Equal
来使基于规则的方法有效。
0.05 + .10 /. {x_ /; x == 0.15 -> "pass"}
1.04 + .10 /. {x_ /; x == 1.14 -> "pass"}
1.05 + .10 /. {x_ /; x == 1.15 -> "pass"}
1.15 /. {x_ /; x == 1.15 -> "pass"}