我正在使用 java 计算两个双数的乘积:106.785 和 217.000,如下所示:
double dd=106.785*217.000;
System.out.println(dd);
我得到的输出是:23172.344999999998
但是当我使用计算器计算时,我得到以下结果:23172.345 我试图通过 IEEE 754 文档以及关于双精度和浮点变量的所有内容,但无法得到正确的解释。谁能帮帮我。任何好的解释都会提前谢谢你
我正在使用 java 计算两个双数的乘积:106.785 和 217.000,如下所示:
double dd=106.785*217.000;
System.out.println(dd);
我得到的输出是:23172.344999999998
但是当我使用计算器计算时,我得到以下结果:23172.345 我试图通过 IEEE 754 文档以及关于双精度和浮点变量的所有内容,但无法得到正确的解释。谁能帮帮我。任何好的解释都会提前谢谢你
IEEE-754 64 位二进制浮点无法表示 106.785。最接近的可表示值为 106.784999999999996589394868351519107818603515625。使用十六进制表示有效数,即 1.ab23d70a3d70a 16 •2 6。该有效位显示为 53 位(“.”之前一位,之后 52 位),这些都是 64 位格式中可用的。如果将一个添加到最后一位,则该值将是 106.7850000000000108002495835535228252410888671875,距离 106.785 更远。
因此,当 Java 处理106.785
源文本时,会将其转换为最接近的值 106.784999999999996589394868351519107818603515625。
当此值乘以 217 时,结果约为 23172.34499999999752617。
对于某些整数M和e ,每个有限 IEEE-754 64 位二进制浮点值具有M •2 e的形式,使得 –2 53 < M < 2 53和 –1074 ≤ e ≤ 971。
为了表示接近 106.785 的值,M设置为 7514326347011850,e设置为 –46。这产生 7514326347011850 •2 -46 = 106.784999999999996589394868351519107818603515625。如果将M加一,则该值变为 106.7850000000000108002495835535228252410888671875。
这个M尽可能大,我们可以让它表示接近 106.785 的东西,因为在 64 位格式中它只有 53 位(52 位明确存储在格式中,而指数暗示了 53 位)。所以M必须在这个范围内,而且必须是整数。因此,我们不能向M添加任何较小的增量;我们只能选择 106.784999999999996589394868351519107818603515625 或 106.7850000000000108002495835535228252410888671875。
注意:在许多文档中,您会看到表格是一个单独的符号、一个有效数字,通常在 [1, 2) 中(但有时在 [0, 1) 中)和一个指数。在这种形式中,有效位有 53 位:“.”之前的整数位,然后是“.”,然后是 52 位小数位。这些形式在数学上是等价的,但整数形式对于某些证明更有用,并且更容易解释M在整数形式中只能以 1 为单位变化。在分数形式中,您必须了解分数只能以 2 –52为单位变化。
如果您担心这种精度,请查看BigDecimal - 但要以性能为代价