Java如何处理浮点不精确度如此奇怪?

时间:2019-06-19 12:05:26

标签: java floating-point precision

与一些程序员进行了有关浮点不精确度的简短讨论之后,我们发现Java的某些行为对我们来说很奇怪。

System.out.println(0.1 + 0.2); // 0.30000000000000004
System.out.println((float) 0.1 + (float) 0.2); // 0.3

由于某种原因,当您将变量强制转换为浮点数时,不正确的信息会消失吗?我们试图研究一些解释,但找不到任何解释。

有没有人知道Java为什么这样表现?

注意:我知道什么是浮点不精确度,而不是为什么当我转换为浮点数时它会消失。我知道这里的精度问题有所不同。

1 个答案:

答案 0 :(得分:1)

Java’s default formatting仅产生足够的十进制数字,以唯一地区分浮点数与相邻的浮点数。

当源文本0.3转换为double时,结果是最接近的double值,即0.299999999999999988897769753748434595763683319091796875。当打印此字时,“ 0.3”就足以唯一标识它,因为0.299999999999999988897769753748434595763683319091796875当然是最接近的值,因为这是我们首先从0.3获得它的方式。

源文本0.10.2产生0.1000000000000000055511151231257827021181583404541015625和 0.200000000000000011102230246251565404236316680908203125。以double格式添加时,结果为0.3000000000000000444089209850062616169452667236328125。请注意,这与上面的数字不同。因此,在打印时,“ 0.3”不足以将其与相邻的值0.299999999999999988897769753748434595763683319091796875区别开。必须产生“ 0.30000000000000004”以表明它是不同的。

将值转换为float时,将使用float的格式,而不是double的格式。格式化float时,只有float中可表示的值才是邻居的候选值。 float中可表示的最接近0.3的值为0.300000011920928955078125。这也是(float) 0.1 + (float) 0.2的结果,并且仅打印“ 0.3”即可与相邻的float值(0.2999999821186065673828125和0.3000000417232513427734375)充分区分开。