Wolfram mathematica 是什么导致了这种奇怪的结果?

Wolfram mathematica 是什么导致了这种奇怪的结果?,wolfram-mathematica,Wolfram Mathematica,我在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 我只是忽略了什么 编辑:在阅读了

我在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
我只是忽略了什么

编辑:在阅读了下面有用的讨论之后,我更改了调度表,改为使用Which语句:

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]

这似乎起到了作用。

欢迎来到机器精度的世界。如果你仔细检查1.05+.10和1.15,你会发现它们并不完全相同:

1.05 + .10 // FullForm

==> 1.1500000000000001`

1.15 // FullForm

==> 1.15`

使用
机器精度
时,除了会产生小错误外,相同的浮点计算在一天中的不同时间会产生稍有不同的结果。这不是一个bug,而是现代硬件浮点体系结构工作原理的一个例子

这意味着您不应该使用依赖于知道
机器精度
数字的精确值的
ReplaceAll
之类的操作。使用
=
(和
=
)可能没有问题,因为它们忽略了
机器精度
数字的最后7位(分别为1位)二进制数字

使用Mathematica算术应该给出准确的结果,无论一天中的什么时间,您可以将其用于示例,如下所示(10位有效数字)


更新:给出了关于浮点运算的更多警告。例如,第80页给出了IEEE 754的不同实现如何产生略有不同的结果的示例,即使是符合标准的

您的替换只适用于精确匹配,而您的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"}

我以为我通过展示其他案例排除了精确性问题。为什么只有一个案例会失败?+1。为了补充答案:可以定义某种公差,而不是原始规则,并将其编码为规则,比如说
With[{eps=0.001},rule[value]:=x_/;Abs[x-value]“pass”]
。这样,您的规则就会起作用,比如说
1.05+.10/{rule[1.15]}
@sapient-network。关键是,您不能依赖于此,即使它偶尔起作用。其他的规则都是巧合。通过这种方式,你引入了在其他语言中被称为“未定义的行为”——也就是说,系统不能保证会发生什么。有趣。我已经很久没有使用Mathematica(>10年前),我认为这始终是为了不回到机器浮点库的限制。@如果您愿意,Heiko Mathematica可以在任意精度下工作,但在许多情况下默认为机器精度,因为这要快得多。从URL的注释末尾开始:“扩展精度80位寄存器算法[…]有其自身的数字代码“抖动精度”问题”。这个问题并没有消失。不同的编译器和优化级别可能会导致或不会导致从80位寄存器到64位内存的存储。这可能会导致这样的怪事。在过去的几年里,我们已经调查了好几个问题。@Daniel你是说旧的问题还没有完全解决?@Alexey它在任何方面都不是“可解决的”,至少在某种意义上,它不是我们可以访问的(这在某种意义上定义为“不是问题”)。太依赖于MKL库的异常对齐处理、BLAS中操作的顺序以及扩展精度寄存器的使用与否。另请参见IEEE 754:仔细阅读可能会发现,即使在同一台机器上,在兼容的硬件/软件中,相同计算的不同结果也会产生。@Alexey I无法想象机器算法会如何实现这一点;使用当前的硬件和软件()是不可能的。对于重要性算术,雅罗斯拉夫提到的方法应该足够了。()有人可能会认为这是一种令人遗憾的情况,但这仍然是事实。@Alexey剥夺你的确定性可能是扩展prec寄存器可能出现的较小问题。对我来说,一个更大的问题是,指数大小大于双prec。因此,溢出可能会发生,也可能不会发生,这取决于影响计算字符串中的中间值是保留在寄存器中还是存储在寄存器中的优化级别。与此相比,条件良好的计算中相对温和的差异让我觉得意义不大,请原谅这个表达式。
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"}