在与一些程序员同事讨论了浮点不精确问题后,我们发现Java有一些对我们来说非常奇怪的行为。
System.out.println(0.1 + 0.2); // 0.30000000000000004
System.out.println((float) 0.1 + (float) 0.2); // 0.3
由于某种原因,当你将变量转换到一个浮点时,不一致就消失了?我们试图找出一些解释,但没有找到。
有人知道为什么Java会这样做吗?
注意:我知道浮点不精确是什么,只是不知道为什么当我转换为浮点时它会消失。我知道不同的精度问题在这里发挥。
Java的默认格式只产生足够的小数位数,以便唯一地将浮点数与相邻的浮点数区分开来。
将源文本0.3
转换为double
时,其结果是最接近的double
值,为0.299999999999999999999988897769753748434595763683319091796875。打印时,“0.3”足以唯一标识它,因为0.29999999999999999999888977697537434595763683319091796875当然是最接近的值,因为这是我们从0.3
中首先得到的值。
源文本0.1
和0.2
生成0.1000000000000000000000055511151231257827021181583404541015625和0.2000000000000000000000555111512312572702118158340246251565404236316680908203125。当以double
格式添加这些值时,结果为0.30000000000000000444089209850062616169452667236328125。注这与上面的数字不同。因此,在打印时,“0.3”不足以将其与相邻值0.299999999999999999999988897769753748434595763683319091796875区分开来。要拿出“0.3000000000000004”,才能说明它与众不同。
将该值转换为float
时,将使用float
的格式,而不是double
的格式。为float
设置格式时,只有float
中可表示的值才是邻居的候选值。最接近0.3的float
中可表示的值是0.3000000011920928955078125。这也是(float)0.1+(float)0.2
的结果,并且通过仅打印“0.3”,它与相邻的float
值(0.2999999821186065673828125和0.3000000417232513427734375)充分区分开来。
这样一个看似简单的数字怎么会“太大”而无法在64位内存中表达呢?
考虑以下代码: 不管我怎么看,这种下溢似乎都没有意义。正如维基百科所说, 下溢是计算机程序中的一种情况,其中计算结果的绝对值比计算机实际存储在CPU内存中的数值小。 但很明显,计算机能够存储与所讨论的值大致接近的数字,因此定义似乎与我在这里看到的行为完全不一致。 有人能解释一下为什么其中一些会产生下溢而另一些不会吗? 这是正确的行为还是错误?
问题内容: 众所周知,(大多数)浮点数没有精确存储(使用IEEE-754格式时)。因此,不应这样做: ......因为它会导致,除非一些特定的任意精度的类型/类使用(BigDecimal的中的Java/Ruby的,bcmath时在PHP中,[数学::BigInt有 / 数学::BigFloat在Perl,仅举几例)来代替。 但是,我想知道为什么当尝试打印该表达式的结果时,脚本语言(Perl和PHP
我正在纠结于一个基本的浮点精度问题。问题就在这里: 运行代码得到“否”
单精度浮动值和双精度浮动值有什么区别?