是什么造成了这个奇怪的Mathematica结果?

Pat*_*ill 4 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"}
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

pass

pass

1.15

pass
Run Code Online (Sandbox Code Playgroud)

我只是忽略了什么?

编辑:阅读下面的有用讨论后,我更改了我的调度表以使用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]
Run Code Online (Sandbox Code Playgroud)

这似乎可以解决问题.

Sjo*_*ies 14

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

1.05 + .10 // FullForm

==> 1.1500000000000001`

1.15 // FullForm

==> 1.15`
Run Code Online (Sandbox Code Playgroud)

  • @sapient network重点是,你不能依赖它,即使它偶尔有效.其他规则巧合.这样做,你会介绍其他语言中称为"未定义行为"的东西 - 也就是说,系统不能保证会发生什么. (3认同)

Yar*_*tov 6

除了在使用时产生小错误外MachinePrecision,相同的浮点计算在一天的不同时间可能会产生略微不同的结果.这不是一个错误,而是现代硬件浮点架构如何工作的副产品

这意味着您不应该使用这样的操作ReplaceAll取决于知道MachinePrecision数字的确切值.使用==(和===)可能没问题,因为它们忽略了最后7个(分别为1个)数字的二进制数字MachinePrecision.

使用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"}
Run Code Online (Sandbox Code Playgroud)

更新:每个计算机科学家应该知道的关于浮点运算的内容给出了关于浮点运算的更多警告.例如,第80页给出了IEEE 754的不同实现如何给出略微不同的结果的示例,即使它们是标准兼容的

  • 从您URL的注释末尾开始:"[...]扩展精度80位寄存器算法对于数字代码有自己的"摆动精度"问题".这个问题并没有消失.不同的编译器和优化级别可能会导致或不存储从80位寄存器到64位存储器的存储.这可能导致如此奇怪.我们在过去几年里研究了几个. (2认同)
  • @Alexey它不是以任何方式"可解决",至少不是通过我们可以访问的方式(在某种意义上将其定义为"不是问题").取决于MKL库的对齐处理变幻莫测,BLAS中的操作顺序以及扩展精度寄存器的使用与否.另请参阅IEEE 754:仔细阅读可以了解在兼容的硬件/软件中,即使在同一台机器上,同一计算的不同结果也会如此. (2认同)
  • @Alexey剥夺您的确定性可能是扩展预寄存器可能出现的较小问题.对我来说,一个更大的问题是指数大小比双精度大.因此,溢出可能发生或不发生,这取决于影响计算字符串中的中间值是保存在寄存器中还是存储的优化级别.与此相比,良好条件计算中相对适度的差异对我来说意义不大,如果你赦免这个表达的话. (2认同)