为什么C++和Java中的这种浮点运算会产生不同的结果

Why does this float operation in C++ and Java give different results?

本文关键字:结果 浮点运算 C++ Java 为什么      更新时间:2023-10-16

我刚刚看到这个网站,并尝试用Java和C++做这件事。为什么用Java编写以下内容会产生0.300000000000000004

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

而用C++编写以下内容会得到0.3?

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

C++标准不能保证使用IEEE 754浮点运算,因此结果实际上是由实现定义的。然而,大多数实现都会这样做

在Java中,floatdouble被定义为IEEE 754浮点类型。此外,您可以将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%016lXn", 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%016Xn", bits);
    }
}

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

C++:  0x3FD3333333333334
Java: 0x3FD3333333333334

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

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

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

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