我无法理解Double.toString()在Java/JVM中的工作方式。
我的理解是,一般而言,分数不能用Double和Float等浮点类型精确表示。例如,206.64的二进制表示形式是206.6399999999999863575794734060764312744140625。那么,为什么(206.64).toString()返回“206.64”而不是“206.6399999999999863575794734060764312744140625”?

Kotlin中的测试代码。

@Test
fun testBigDecimalToString() {
    val value = 206.64
    val expected = "206.64"

    val bigDecimal = BigDecimal(value)

    assertEquals(expected, value.toString()) // success
    assertEquals(expected, bigDecimal.toString()) // failed. Actual: 206.6399999999999863575794734060764312744140625
}

最佳答案

在打印floatdouble时看到的位数是Java规则的结果,Java规则将floatdouble缺省转换为十进制。
Java的浮点数默认格式使用最少的有效十进制数字来将数字与附近的可表示数字区分开。1
在您的示例中,源文本中的206.64被转换为double值206.6399999999999863575794734060764312744140625,因为在double类型中可表示的所有值中,最接近206.64的值。下一个较低和下一个较高的值是206.639999999999957957870870002002068996429443359375和
206.640000000000014779288903810083866119384765625。
当打印此值时,Java只需要打印“206.64”,因为这足以使我们可以从其邻居206.6399999999999999957935870043002068996429443359375和中选择double值206.6399999999999863575794734060764312744140625
206.640000000000014779288903810083866119384765625。请注意,从206.63999…的9s末尾开始,第一个值与206.64的差值为1.1364…,而第三个值206.64000…的差值则为.1477…。因此,当Java打印“206.64”时,它表示要打印的double的值是最接近的可表示值,即206.6399999999999863575794734060764312744140625的值,而不是更远的206.6400000000000147792889038100838661193847656的值。
脚注
1 Java SE 10的规则可以在toString(float d)部分的java.lang.float文档中找到。 double文档与此类似。段落中最相关的部分为粗体:

10-04 16:21