c++ - 如果两种语言都遵循 IEEE 754,那么两种语言的计算结果是否相同?

标签 c++ floating-point precision scilab rounding-error

我正在将程序从 Scilab 代码转换为 C++。特别是一个循环产生的结果与原始 Scilab 代码略有不同(这是一段很长的代码,所以我不打算将它包含在问题中,但我会尽力在下面总结问题)。

问题是,循环的每一步都使用上一步的计算。此外,计算之间的差异仅在第 100,000 次迭代(大约 300,000 次)时变得明显。

注意:我正在使用“format(25);”将我的 C++ 程序的输出与 Scilab 5.5.2 的输出进行比较命令。这意味着我正在比较 25 位有效数字。我还想指出,我理解在一定数量的位之后如何不能保证精度,但在评论之前阅读下面的部分。到目前为止,两种语言之间的所有计算在 25 位以内都是相同的。

为了深入了解这个问题,到目前为止我已经尝试过:

  1. 检查正在使用的数据类型:

我已经设法确认 Scilab 正在使用 IEEE 754 double (根据语言文档)。此外,根据维基百科,C++ 不需要将 IEEE 754 用于 double ,但据我所知,我在 C++ 中使用 double 的任何地方都与 Scilab 的结果完全匹配。

  1. 检查超越函数的使用:

我还从 What Every Computer Scientist Should Know About Floating-Point Arithmetic 了解到 IEEE 不要求先验函数精确舍入。考虑到这一点,我比较了这些函数(sin()、cos()、exp())在两种语言中的结果,结果再次显示相同(最多 25 位数字)。

  1. 其他函数和预定义值的使用:

对于sqrt()和pow()的使用,我重复了上面的步骤。以及 Pi 的值(我在 C++ 中使用 M_PI,在 Scilab 中使用 %pi)。同样,结果是一样的。

  1. 最后,我重写了循环(非常仔细)以确保两种语言的代码相同。

注意:有趣的是,我注意到对于上述所有计算,两种语言之间的结果比实际计算结果(浮点运算除外)的匹配程度更高。例如:

使用 Wolfram Alpha 的 sin(x) 值 = 0.123456789.....

使用 Scilab 和 C++ 的 sin(x) 值 = 0.12345yyyyy.....

即使使用 Scilab 或 C++ 计算的值开始与实际结果(来自 Wolfram)不同。每种语言的结果仍然相互匹配。这让我相信大多数值都是以相同的方式计算的(在两种语言之间)。尽管 IEEE 754 不要求它们。


我最初的想法是上述前三点之一在两种语言之间的实现方式不同。但据我所知,一切似乎都产生了相同的结果。

是否有可能即使这些循环的所有输入都相同,但结果可能不同?可能是因为随着时间的推移累积了一个非常小的错误(超过我能看到的 25 位数字)?如果是这样,我该如何着手解决这个问题?

最佳答案

不,编号系统的格式不能保证不同语言的函数得到相同的答案。

函数,例如sin(x),可以使用相同的语言(以及不同的语言)以不同的方式实现。 sin(x) 函数就是一个很好的例子。许多实现将使用查找表或带插值的查找表。这具有速度优势。但是,某些实现可能会使用泰勒级数来评估函数。一些实现可能会使用多项式来得出一个近似值。

具有相同的数字格式是不同语言之间需要解决的一个障碍。功能实现是另一个。

请记住,您还需要考虑平台。使用 80 位浮点处理器的程序将与使用 64 位浮点软件实现的程序产生不同的结果。

关于c++ - 如果两种语言都遵循 IEEE 754,那么两种语言的计算结果是否相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37928129/

相关文章:

c - 对于 C 中的 pow() 等函数,将精度提高到小数点后 20 位

precision - 计算 (x-sin(x))/x^3 的数值稳定方法

c++ - 使用 RapidXML 读取 XML 节点

c++ - 是否可以将 QtConcurrent::run() 与类的函数成员一起使用

c - float 输出不正确

减法时PHP浮点计算错误

c++ - 使用C++编程时,我应该如何在win32中创建一个子窗口?

java - 将 OpenCV 代码从 C++ 转换为 Java

python - 如何从 Python 中的文件中提取 float ?

c - C 中的 GMP 库 - 如何使添加更精确?