我对Java是否使用IEEE 754标准来实现其浮点运算感兴趣。 Here我在文档中看到了这种情况:
据我了解,IEEE 754的积极方面是提高浮点运算的精度,因此,如果我在Java中使用double
或float
,计算的精度是否会与BigDecimal
中的相同?如果不是,那么在 Math
类中使用IEEE 754标准有什么意义呢?
最佳答案
IEEE-754为多种浮点类型定义了标准。多年以来,它们都是二进制浮点数。这就是Java的float
和double
的含义:float
是32位IEEE-754二进制浮点值(标准称为 binary32
)。 double
是64位的(标准称为 binary64
)。这些二进制浮点数对于计算机而言非常有效,但是由于它们以二进制形式工作,而我们以十进制形式工作,因此存在一些期望值不匹配的情况。例如,0.1
不能精确地存储在double
中,并且会出现诸如0.1 + 0.2
之类的奇怪现象,结果变成0.30000000000000004
。有关详细信息,请参见Is floating point math broken?。例如,它们不是财务计算的好选择。BigDecimal
是一个Java类,它以任意精度实现十进制小数。它比使用double
慢得多,但是结果符合我们的十进制想法(例如0.1 + 0.2
将是0.3
)。
IEEE-754的2008版增加了重要的新格式,尤其是 decimal32
, decimal64
和 decimal128
。这些是十进制浮点数,因此它们的工作方式与我们相同。 0.1
可以准确地存储在decimal64
中。 0.1 + 0.2
是0.3
中的decimal64
。但是,据我所知,它们与您的问题并没有真正的关系。
由于BigDecimal
在一定程度上早于IEEE-754 2008,因此它定义了自己的语义。
JDK9在Math
中添加了执行IEEE-754 2008规范定义的操作的新操作(例如 fma
,它执行fused multiply-add),因此为了清楚起见,它引用IEEE-754 2008规范定义了这些操作。
更多阅读:
BigDecimal
JavaDoc