当前位置: 首页 > 知识库问答 >
问题:

为什么相同的代码在不同的机器上产生两种不同的fp结果?

越鸿才
2023-03-14

这是代码:

#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)或这里(GCC)上尝试:

errorLn2per12 = 9.3702823278363212011754512786865234375e-12

相反,这里(GCC):

errorLn2per12 = 9.368505970996920950710773468017578125e-12

这是不同的。这是由于机器厄普西隆?还是编译器精度标志?还是不同的IEEE评估?

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

共有1个答案

龚弘业
2023-03-14

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

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

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

如果您希望 log 在各个平台和编译器之间给出完全相同的结果,则必须仅使用 -*/sqrt 自己实现它(或者查找具有此保证的库)。并在此过程中避免一系列陷阱。

如果您普遍需要浮点决定论,我强烈建议您阅读本文,了解您面前的问题有多大:https://randomascii.wordpress.com/2013/07/16/floating-point-determinism/

 类似资料:
  • 当我跑的时候。使用CPLEX的NET 4应用程序,我在不同的机器上得到不同的输出。在我的开发机器上,CPLEX输出一个结果(异常并卡在某个大值上),在所有其他机器上,结果都可以。 首先,我认为它与操作系统有关,因为我的开发机器上同时有视窗7 x64和视窗8 x64,所以我尝试在两个系统上运行应用程序。结果是一样的——有缺陷。 然后我试着在两台不同的台式机上运行,效果很好。我甚至在虚拟机内部进行了尝

  • 问题内容: 范例1: 输出为: 范例2: 输出: 我只是不明白为什么将saySomething设为非静态会导致第二次调用saySomething调用Cow版本而不是Animal版本。我的理解是, 这两种情况都是输出。 问题答案: 静态方法在编译时绑定到其类,并且不能多态使用。在Animal上声明“静态”方法时,该方法永远绑定到Animal类,并且不能被覆盖。静态方法绑定到Class对象,而不是Cl

  • https://leetcode.com/problems/find-all-numbers-dispapered-in-an-array/discuss/93007/simple-java-in-place-sort-solution 你能查一下上面的链接吗? 我看不懂密码 然后,第一个只是简单地使用我们可以检查是不是值。 第二个, 它最终也是一样的东西,只是为了证明索引值=index+1。 但

  • 我编写了以下代码,在我的计算机上运行良好,但在其他计算机上返回null。你能帮我解决这个问题吗。 这些是我的计算机输出的一部分: ['i'、'have'、'one'、'generalized'、'rule'、'where'、'in'、'shellscript'、'i'、'check'、'for'、'all'、'need'、……idea'] 其他计算机结果: [('', '', '', ''), (

  • 问题内容: 这个问题与PHP的实现有关。对于此问题,不计算盐的前7个字符,因此盐’ ‘的长度为1,因为它仅是盐的1个字符和元数据的7个字符。 当使用长度超过22个字符的盐字符串时,生成的哈希值不会发生变化(即,截断),而当使用长度小于21个字符的字符串时,盐将被自动填充(显然带有’ ‘字符);这非常简单。但是,如果给定一个Salt 20个字符和Salt 21个字符,并且除了21个长度的salt的最

  • 我在试验inttype. h时做的简单程序: 在我的手机(64位八核ARN LTE Soc Android 10)它的工作原理很好: 但在我的计算机(64位x86 Windows 10)上,我得到: 将bool更改为uint8_t不会影响它。 编辑:我尝试用MinGW-w64 GCC C99和C17编译。