【问题标题】:Why does this float operation in C++ and Java give different results?为什么 C++ 和 Java 中的这种浮点运算会给出不同的结果?
【发布时间】:2014-09-29 21:45:37
【问题描述】:

我刚刚遇到this 网站并尝试在 Java 和 C++ 中执行此操作。为什么用 Java 编写以下代码会给出 0.30000000000000004

double x = 0.1 + 0.2;
System.out.print(x);

而用 C++ 编写以下代码会得到 0.3?

double x = 0.1 + 0.2;
cout<<x;

【问题讨论】:

  • 在 C++ 中,以更高的精度打印:cout &lt;&lt; setprecision(15) &lt;&lt; x。我预测结果是一样的,它只是在 Java 中默认打印更多的数字。
  • 了解printcout 格式选项
  • @RuchiraGayanRanaweera 你知道“实际”发生了什么吗?
  • 默认情况下,C++ 输出流运算符打印六位数的浮点值。如果这六位数字在小数点后有尾随零,则零将被删除。
  • @MattAdams 谢谢马特!知道了!所以,我们要用 C++ 做的是std::cout&lt;&lt;std::setprecision(17)&lt;&lt;std::fixed&lt;&lt;x; 以获得相同的输出。他们将其搁置为“太宽泛”! :D

标签: java c++


【解决方案1】:

C++ 标准不能保证使用IEEE 754 floating point arithmetic,因此结果实际上是实现定义的。但是,大多数实现都会这样做。

在 Java 中,floatdouble are defined to be IEEE 754 floating point types。此外,您可以将 strictfp 修饰符添加到类或方法声明中,以要求使用严格的 IEEE 754 浮点运算,即使是中间结果。

在处理浮点数时,如有疑问,查看实际的位表示通常很有用。

#include <cstdint>
#include <cstdio>

int
main()
{
  static_assert(sizeof(double) == sizeof(uint64_t), "wrong bit sizes");
  const double x = 0.1 + 0.2;
  const uint64_t bits = *reinterpret_cast<const uint64_t *>(&x);
  printf("C++:  0x%016lX\n", bits);
  return 0;
}
public final class Main {
    public static void main(final String[] args) {
        final double x = 0.1 + 0.2;
        final long bits = Double.doubleToLongBits(x);
        System.out.printf("Java: 0x%016X\n", bits);
    }
}

当我在我的计算机上执行这两个程序(带有 GCC 和 OpenJDK 的 GNU/Linux)时,输出是

C++:  0x3FD3333333333334
Java: 0x3FD3333333333334

这表明两者产生完全相同的结果。但是,可移植程序不应依赖于此。

【讨论】:

    【解决方案2】:

    在 IEEE 浮点表示中,0.1 和 0.2(或 0.3)都不是精确值。只有 2 的负幂及其组合为(例如 0.5、0.25、0.75 ...)。

    因此,您看到的差异只是 Matt Adams 所述的默认输出格式的差异。

    【讨论】:

      【解决方案3】:

      确定您的精度级别,并专门为输出流设置,应该显示相同

      【讨论】:

        猜你喜欢
        • 2011-01-21
        • 1970-01-01
        • 2012-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-31
        • 2015-11-16
        相关资源
        最近更新 更多