在 Java 中使用 double 保持精度

新手上路,请多包涵
public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total += 5.6;
        total += 5.8;
        System.out.println(total);
    }
}

上面的代码打印:

 11.399999999999

我如何才能让它打印(或能够将其用作)11.4?

原文由 Deinumite 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 995
2 个回答

正如其他人所提到的,如果您想要精确表示 11.4,您可能想要使用 BigDecimal 类。

现在,稍微解释一下为什么会发生这种情况:

Java 中的 floatdouble 原始类型是 浮点数,其中数字存储为分数和指数的二进制表示。

更具体地说,诸如 double 类型的双精度浮点值是 64 位值,其中:

  • 1 位表示符号(正或负)。
  • 11 位为指数。
  • 有效数字为 52 位(小数部分为二进制)。

这些部分组合起来产生一个值的 double 表示。

(来源: 维基百科:双精度

有关如何在 Java 中处理浮点值的详细说明,请参阅 第 4.2.3 节:Java 语言规范的浮点类型、格式和值

The byte , char , int , long types are fixed-point numbers, which are exact representions of numbers.与定点数不同,浮点数有时(可以安全地假设“大部分时间”)无法返回数字的精确表示。这就是您最终得到 11.399999999999 的原因 5.6 + 5.8

当需要一个精确的值(例如 1.5 或 150.1005)时,您需要使用其中一种能够精确表示数字的定点类型。

正如已经多次提到的,Java 有一个 BigDecimal 类,它可以处理非常大的数字和非常小的数字。

来自 BigDecimal 类的 Java API 参考:

不可变的、任意精度的有符号十进制数。 BigDecimal 由一个任意精度的整数未缩放值和一个 32 位整数刻度组成。如果为零或正数,则刻度是小数点右侧的位数。如果为负数,则将数字的未缩放值乘以 10 的负数次方。因此 BigDecimal 表示的数字的值是 (unscaledValue × 10^-scale)。

Stack Overflow 上有很多关于浮点数及其精度的问题。以下是可能感兴趣的相关问题列表:

如果您真的想深入了解浮点数的基本细节,请查看 每个计算机科学家应该了解的关于浮点运算的知识

原文由 coobird 发布,翻译遵循 CC BY-SA 3.0 许可协议

当您输入双精度数时,例如 33.33333333333333 ,您得到的值实际上是最接近的可表示双精度值,即:

 33.3333333333333285963817615993320941925048828125

将其除以 100 得到:

 0.333333333333333285963817615993320941925048828125

这也不能表示为双精度数,因此它再次四舍五入到最接近的可表示值,即:

 0.3333333333333332593184650249895639717578887939453125

当您打印出此值时,它会 再次 四舍五入为 17 位十进制数字,给出:

 0.33333333333333326

原文由 Stephen Canon 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题