【问题标题】:How to confirm whether different results are due to differences in floating point handling?如何确认不同的结果是否是由于浮点处理的不同?
【发布时间】:2012-03-01 15:22:50
【问题描述】:

我已经将一个相对简单的算法从 C++ 转换为对 double 类型的数字执行大量计算的 Java,但是在两个平台上运行该算法但同一台机器产生的结果略有不同。该算法将许多双精度数和整数相乘并求和。我在 Java 算法中将整数加倍; C 算法不强制转换。

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

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

(打印忽略小数位)

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


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

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

【问题讨论】:

  • 您在 Java 版本中使用了什么数据类型?
  • 差别很大,我怀疑这可能是由舍入错误引起的。我的猜测是你在某个地方犯了错误。除非你做一些极端的事情,比如除以 1E300 之类的。
  • 浮点错误累积到 1% 的差异的可能性很小,但如果您运行的算法在数值上不稳定,这当然是可能的(“不稳定”意味着大约是“混乱的小弟”) .显然,从结果中无法判断您没有在 Java 代码中意外写入 result -= 611438,因此仅通过查看结果。但是,如果您可以使用 float 代替 double 在 C++ 中运行计算,那么您可能会知道精度的重要性。
  • 使用调试器或打印语句,以全精度显示算法中的每个中间值。希望这将确定值开始分歧的单个步骤。当您确定了这一步后,请回到我们这里。
  • 您还可以根据代码的优化方式获得差异。例如0.1 + 0.1 + 0.1 + 0.1 + 0.15 * 0.1 我不希望根据您的操作而得到小于第 12 到第 15 位的差异。

标签: java c++ floating-point


【解决方案1】:

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

【讨论】:

  • 除非我遗漏了什么,否则四舍五入可能会减少出现问题的次数,但它不会消除所有问题?我认为,您可能仍会将精度差异汇总到不太精确的圆形浮点数中?就像如果在 cpu 上给出 95.499999994 而另一个给出 95.499999995 并且您以该精度四舍五入,即使小数较少,您也会得到不同的值?
【解决方案2】:

AFAIK 有时 double 字面量的值可能会在两个 c++ 编译器版本之间发生变化(当用于将源转换为下一个最佳 double 值的算法发生变化时)。

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

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

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

【讨论】:

  • 在这种情况下,检查逐步输出确定了不同的步骤,并指出了数据中的差异。已更正算法一致。
【解决方案3】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-04
    • 2019-10-29
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多