【问题标题】:Why this same code produce two different fp results on different Machines?为什么相同的代码在不同的机器上产生两个不同的 fp 结果?
【发布时间】:2019-07-08 17:00:05
【问题描述】:

代码如下:

#include <iostream>
#include <math.h>

const double ln2per12 = log(2.0) / 12.0;

int main() {
    std::cout.precision(100);
    double target = 9.800000000000000710542735760100185871124267578125;
    double unnormalizatedValue = 9.79999999999063220457173883914947509765625;
    double ln2per12edValue = unnormalizatedValue * ln2per12;
    double errorLn2per12 = fabs(target - ln2per12edValue / ln2per12);
    std::cout << unnormalizatedValue << std::endl;
    std::cout << ln2per12 << std::endl;
    std::cout << errorLn2per12 << " <<<<< its different" << std::endl;
}

如果我在我的机器上尝试 (MSVC) 或 here (GCC):

errorLn2per12 = 9.3702823278363212011754512786865234375e-12

取而代之的是here (GCC):

errorLn2per12 = 9.368505970996920950710773468017578125e-12

这是不同的。是因为Machine Epsilon?还是编译器精度标志?或者不同的IEEE 评价?

这种漂移的原因是什么?问题似乎在fabs() 函数中(因为其他值似乎相同)。

【问题讨论】:

  • @MatthieuBrucher:请不要!这不是那个问题的重复!它特定于每个平台。请仔细阅读
  • 显然不是重复
  • @markzzz 链接可能会过时,如果这些链接包含重要信息,问题就会变得毫无价值。尝试使问题自成一体。
  • @markzzz 标志应该在问题中,而不是在外部链接后面。就我而言,如果我必须点击一个链接,它不存在作为问题的一部分。

标签: c++ floating-point floating-accuracy


【解决方案1】:

即使没有-Ofast,C++ 标准也不要求实现与log(或sin,或exp 等)完全相同,只要它们在几个ulp 之内(即可能有在最后一个二进制位置有一些不准确)。这允许更快的硬件(或软件)近似,每个平台/编译器可能会做不同的事情。

(唯一一个在所有平台上都能得到完美结果的浮点数学函数是sqrt。)

更烦人的是,你甚至可能在编译(编译器可能使用一些内部库来精确到float/double 允许常量表达式)和运行时(例如硬件支持的近似值)之间得到不同的结果。

如果您希望 log 在平台和编译器之间提供完全相同的结果,您必须自己使用 +、-、*、/ 和 sqrt(或找一个有这个保证的图书馆)。并避免一路走来的一大堆陷阱。

如果您通常需要浮点确定性,我强烈建议您阅读这篇文章以了解您面临的问题有多大:https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-02-13
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
相关资源
最近更新 更多