-2

我正在使用 java 计算两个双数的乘积:106.785 和 217.000,如下所示:

    double dd=106.785*217.000;
    System.out.println(dd);

我得到的输出是:23172.344999999998

但是当我使用计算器计算时,我得到以下结果:23172.345 我试图通过 IEEE 754 文档以及关于双精度和浮点变量的所有内容,但无法得到正确的解释。谁能帮帮我。任何好的解释都会提前谢谢你

4

2 回答 2

3

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。


对于某些整数Me ,每个有限 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为单位变化。

于 2013-10-17T15:51:35.753 回答
0

如果您担心这种精度,请查看BigDecimal - 但要以性能为代价

于 2013-10-17T15:33:23.587 回答