编译器以不同的方式处理数学?

compilers processing maths differently?

本文关键字:处理 方式 编译器      更新时间:2023-10-16

我做了一个代码来查找给定点的函数的导数。代码读取

#include"stdafx.h"
#include<iostream>

using namespace std;
double function(double x) {
return (3 * x * x);
}

int main() {
double x, y, dy, dx;
cin >> x;
y = function(x);
dx = 0.00000001;
dy = function(x + dx) - y;
cout << "Derivative of function at x = " << x << " is " << (double)dy / dx;
cin >> x;
}

现在我的大学使用turbo C++作为IDE和编译器,而在家里我有Visual Studio(因为TC ++在900p屏幕上看起来很糟糕,但开玩笑)。当我在大学PC上尝试类似的程序时,结果非常混乱,并且比我在家里得到的要准确得多。例如:

例子:

x = 3

@College结果 = 18.something

@Home结果 = 18(精确无小数点)

x = 1

@College结果 = 6.000.....某物

@Home结果 = 6(精确无小数点)

非常大的问题:

为什么不同的编译器给出不同的结果?

我 90% 确定两种情况下的结果是相同的,您看到差异的唯一原因是不同的输出格式。 对于 64 位 IEEE 双精度数学,这些计算的精确结果可能分别为 17.9999997129698385833762586116790771484375 和 6.0000000079440951594733633100986480712890625。

如果要验证该假设,可以通过以下方式打印双精度值:

void printDoubleAsHex( double val )
{
const uint64_t* p = (const uint64_t*)( &val );
printf( "%" PRIx64 "n", *p );
}

并验证两个编译器中的输出相同。

但是,您的两个编译器确实以不同的方式编译您的代码的可能性也有 10%。这种情况并不少见,它甚至可能发生在相同的编译器上,但不同的设置/标志/选项。

最可能的原因是不同的指令集。默认情况下,许多现代编译器会为像您这样的代码生成 SSE 指令,较旧的编译器会生成遗留的 x87 代码(x87 在堆栈上的 80 位浮点值上运行,在这些向量寄存器上的 32 位或 64 位 FP 值上运行 SSE,因此精度存在差异)。另一个原因是舍入模式不同。另一个是特定于编译器的优化,例如Visual C++中的/fp。