java中的双乘法

时间:2013-10-17 15:25:06

标签: floating-point

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

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

我得到的输出是:         23172.344999999998

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

2 个答案:

答案 0 :(得分:3)

106.785在IEEE-754 64位二进制浮点中无法表示。最接近的可表示的值是106.784999999999996589394868351519107818603515625。使用十六进制作为有效数字,这是1.ab23d70a3d70a 16 •2 6 。该有效数字以53位(一个在“。”之前,52之后)显示,这些都是64位格式的。如果将一个添加到最后一位,则该值将为106.7850000000000108002495835535228252410888671875,这远离106.785。

因此,当Java在源文本中处理106.785时,它会将其转换为最接近的值106.784999999999996589394868351519107818603515625。

当此值乘以217时,结果约为23172.34499999999752617。


对于某些整数,每个有限的IEEE-754 64位二进制浮点值的格式为 M •2 e M 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 rd 。所以 M 必须在此范围内,并且必须是整数。因此,我们无法向 M 添加任何较小的增量;我们坚持选择106.784999999999996589394868351519107818603515625或106.7850000000000108002495835535228252410888671875。

注意:在许多文档中,您将看到表单作为单独的符号,通常在[1,2]中的有效数字(但有时在[0,1)中)和指数。在这种形式中,有效数字具有53位:“。”之前的整数位,然后是“。”,然后是52位分数。表单在数学上是等价的,但整数形式对于某些证明更有用,并且更容易解释 M 只能以整数形式的单位改变。在分数形式中,您必须了解分数只能以2 -52 为单位进行更改。

答案 1 :(得分:0)

如果你担心这样的精确度,请查看BigDecimal - 但是以性能为代价