为什么在C++和Java中进行的浮点运算会得出不同的结果?

3
我刚刚发现了这个网站http://floating-point-gui.de/,并尝试使用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;

4
在 C++ 中以更高的精度打印: cout << setprecision(15) << x。我预测结果是相同的,只是在 Java 中默认情况下会打印更多位数。 - Igor Tandetnik
1
阅读有关printcout格式选项的内容。 - quantdev
2
@RuchiraGayanRanaweera 你知道 'actually' 到底发生了什么吗? - Shravan
7
默认情况下,C++ 输出流运算符会使用六位小数打印浮点数。如果小数点后的这六位数字末尾是零,则会将这些零去掉。 - Matt Adams
这个链接可能对你有帮助:这里 - Mohit Jain
显示剩余4条评论
3个回答

4
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%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),输出结果为:
C++:  0x3FD3333333333334
Java: 0x3FD3333333333334

这表明两者产生完全相同的结果。然而,可移植程序不应依赖此功能。

2
在IEEE浮点表示中,0.1和0.2(以及0.3)都不是精确的值。只有2的负幂及其组合才是(例如0.5、0.25、0.75...)。所以你看到的差异只是输出格式的差异,正如Matt Adams所述。

0

确定您的精确度水平,并为输出流明确设置相同的值


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接