如何确认不同的结果是否是由于浮点处理的差异

How to confirm whether different results are due to differences in floating point handling?

本文关键字:是否是 结果是 于浮点 处理 结果 确认 何确认      更新时间:2023-10-16

我已经将一个相对简单的算法从C++转换为Java,该算法对double类型的数字执行大量计算,但在两个平台上运行该算法,但在同一台机器上会产生略有不同的结果。该算法对大量的double和int进行乘法和求和。我在Java算法中把int转换为double;C算法不进行投射。

例如,在一次运行中,我得到了以下结果:

  • (Java)64684970
  • (C++)65296408

(打印忽略小数位)

当然,我的算法中可能会有错误,但在我开始花时间调试之前,有没有可能用C++和Java中不同的浮点处理来解释这种差异?如果是,我能证明这就是问题所在吗?


更新-类型不同的地方是两个int之间的乘积,然后将其添加到一个运行的双整数中。修改了C代码,目前在两者中:

mydouble += (double)int1 * (double)int2

您可以使用相同的精度为每个算法添加舍入。这将允许每个计算以相同的方式处理数据。如果你使用它,它将消除算法的问题,因为对于C++和Java版本,数据在方程的每一步都将使用相同的精度

AFAIK在两个c++编译器版本之间,双文本的值有时会发生变化(用于将源转换为下一个最佳双值的算法发生变化)。

此外,在一些cpu上,浮点寄存器大于64/32位(更大的范围和精度),这对结果的影响取决于编译器和JIT如何将值移入和移出这些寄存器——这可能在java和c++之间有所不同。

Java使用strictftp关键字来确保只使用64/32位的精度,但这会带来运行时成本。还有大量选项可以通过抛出IEEE标准制定的保证性/规则来影响c++编译器如何处理和优化浮点计算。

如果算法基本相同,那么可以检查相同输入的第一个差异出现在哪里。

在Java中,double是一个64位浮点数。在C++中,double是一个保证至少具有32位精度的浮点数。

要找出系统上C++double的实际大小(以字节为单位),请使用sizeof(double)。

如果结果是sizeof(double)==8,那么几乎可以肯定的是,这种差异是由于从一种语言到另一种语言的翻译中的错误,而不是浮点数处理中的差异。

(从技术上讲,字节的大小取决于平台,但大多数现代体系结构使用8位字节。)