为什么0.29999999999999998转换为0.3?

Why is 0.29999999999999998 converted to 0.3?

它在内部是如何工作的?

它如何决定将 0.29999999999999998 转换为 0.3,即使 0.3 不能用二进制表示?

这里还有一些例子:

scala> 0.29999999999999998
res1: Double = 0.3

scala> 0.29999999999999997
res2: Double = 0.3

scala> 0.29999999999999996
res3: Double = 0.29999999999999993

scala> 0.29999999999999995
res4: Double = 0.29999999999999993

涉及两个转换。

首先将 0.29999999999999998 转换为 0.299999999999999988897769753748434595763683319091796875,这是最接近的可表示数字。

接下来将0.299999999999999988897769753748434595763683319091796875转为十进制打印。 0.3 也是转换为 0.299999999999999988897769753748434595763683319091796875 的数字之一,它是被打印出来的,因为它太短了。

每个有限双精度数都可以精确表示为小数。通常,默认输出不会尝试打印准确的值,因为它可能很长——比上面的例子长得多。一个常见的选择是打印最短的小数部分,以便在输入时转换为双精度数。这两种转换都是使用非平​​凡算法完成的。有关输出算法的一些讨论和参考,请参阅 Algorithm to convert an IEEE 754 double to a string?

============================================= =================

评论中对值 0.30000000000000004 进行了一些讨论。我同意 Rick Regan 和 Jesper 的评论,但认为添加到这个答案中可能会有用。

最接近0.30000000000000004的double的精确值为0.3000000000000000444089209850062616169452667236328125。 [0.30000000000000001665334536937734810635444750213623046875, 0.3000000000000007216449660063517512753605844259033203125] 范围内的所有十进制数字,并且没有将范围内的数字稍微转换为偶数。 0.3000000000000000 超出范围,因此它没有足够的数字。 0.30000000000000004在范围内,所以不需要更多的数字来正确识别double。

注意在Scala中Double(见IEEE 754 Standard and IEEE Floating-Point Arithmetic),原始声明值四舍五入,

val x = 0.29999999999999998
x: Double = 0.3

"0.29999999999999998".toDouble
Double = 0.3

多达

0.2999999999999999999999999999999999999999999999999999999999998
Double = 0.3

同样在BigDecimal中,对于任意精度的十进制浮点表示(参见API),类型Double(构造函数的参数)的原始值首先被舍入,即

BigDecimal(0.29999999999999998) == 0.3
Boolean = true

BigDecimal(0.29999999999999998)
scala.math.BigDecimal = 0.3

然而,原始值的 textual 声明未被解释为 Double,因此四舍五入,

BigDecimal("0.29999999999999998") == 0.3
Boolean = false

BigDecimal("0.29999999999999998")
scala.math.BigDecimal = 0.29999999999999998