如何在Java中避免浮点数或双精度的浮点精度错误?

2022-09-01 08:14:03

我有一个非常烦人的问题,在Java中有大量的浮点数或双精度。基本上,这个想法是,如果我执行:

for ( float value = 0.0f; value < 1.0f; value += 0.1f )
    System.out.println( value );

我得到的是:

0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001

我知道存在累积的浮动精度误差,但是,如何摆脱这一点?我尝试使用双精度到一半的错误,但结果仍然相同。

有什么想法吗?


答案 1

没有将 0.1 精确表示为 或 。由于此表示错误,结果与预期略有不同。floatdouble

您可以使用以下几种方法:

  • 使用文字时,仅显示所需数量的数字。当检查相等性时,无论哪种方式都允许较小的公差。double
  • 或者,使用允许您准确存储尝试表示的数字的类型,例如,可以精确地表示 0.1。BigDecimal

示例代码:BigDecimal

BigDecimal step = new BigDecimal("0.1");
for (BigDecimal value = BigDecimal.ZERO;
     value.compareTo(BigDecimal.ONE) < 0;
     value = value.add(step)) {
    System.out.println(value);
}

在线查看:ideone


答案 2

您可以使用 BigDecimal 等类来避免此特定问题。 而且,作为IEEE 754浮点,它们的设计不是完全准确的,而是设计得很快。但请注意乔恩下面的观点:不能准确地表示“三分之一”,就像不能准确地表示“十分之一”一样。但对于(比如)金融计算来说,像这样的类往往是要走的路,因为它们可以以我们人类倾向于思考它们的方式表示数字。floatdoubleBigDecimaldoubleBigDecimal


推荐