Floating point java中的双重乘法

Floating point java中的双重乘法,floating-point,Floating Point,我正在使用java计算两个双精度数字的乘积:106.785和217.000,如下所示: double dd=106.785*217.000; System.out.println(dd); 我得到的结果是: 23172.3449999998 但当我用计算器计算时,我得到了以下结果: 23172.345 我试图阅读IEEE 754文档以及关于双精度变量和浮点变量的所有内容,但没有得到正确的解释。谁能帮帮我吗。 任何好的解释都可以 提前感谢您如果您担心这样的精度,请查看—但以性能为

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

    double dd=106.785*217.000;
    System.out.println(dd);
我得到的结果是: 23172.3449999998

但当我用计算器计算时,我得到了以下结果: 23172.345 我试图阅读IEEE 754文档以及关于双精度变量和浮点变量的所有内容,但没有得到正确的解释。谁能帮帮我吗。 任何好的解释都可以
提前感谢您

如果您担心这样的精度,请查看—但以性能为代价

106.785不能用IEEE-754 64位二进制浮点表示。最接近的可表示值为106.78499999996589394868351519107818603515625。使用十六进制作为有效位,这是1.ab23d70a3d70a16•26。该有效位显示为53位(在“.”之前一位,在“.”之后52位),这些都是64位格式中可用的。如果在最后一位加上一个,则该值将为106.7850000000000108002495835535228252410888671875,比106.785更远

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

当该值乘以217时,结果约为23172.3449999999752617


对于某些整数M和e,每个有限IEEE-754 64位二进制浮点值的形式为M•2e,因此-253 为了表示接近106.785的值,M设置为7514326347011850,e设置为–46。这将产生7514326347011850•2-46=106.78499999996589394868351519107818603515625。如果将一添加到M,该值将变为106.7850000000000108002495835535228252410888671875

这个M是我们可以使其表示106.785附近的值的最大值,因为64位格式中只有53位(52位显式存储在该格式中,53位由指数表示)。所以M必须在这个范围内,它必须是一个整数。因此,我们不能向M添加任何较小的增量;我们只能选择106.78499999996589394868351519107818603515625或106.7850000000000108002495835535228252410888671875


注意:在许多文档中,您会将该形式视为一个单独的符号、[1,2]中的有效位(但有时在[0,1]中)和一个指数。在这种形式中,有效位有53位:在“.”之前是一个整数位,然后是“.”,然后是52个分数位。这些形式在数学上是等价的,但整数形式对于某些证明更有用,并且更容易解释,在整数形式中,M只能以1为单位变化。在分数形式中,您必须理解分数只能以2–52为单位变化。

必须:所有浮点数学都有s有些精度错误。不管怎么说,0.344999999999999是0.345如果你的值是0.000000000002,它真的有区别吗?如果有,那么就使用它。@AndyG:不是这样。在这种情况下,乘法本身就可以了。问题是从十进制表示到二进制浮点的转换。106.785不能准确地用二进制浮点表示。如果您对计算机科学感兴趣,我有一本非常好的读物给您!谢谢您的回答,Eric,但能否告诉我为什么不能转换此值,以便我可以在中处理此类问题future@AshishSood:我添加了一些关于哪些值可以在IEE中表示的文本E-754二进制浮点。@Eric谢谢您的帮助。我不关心精度。据我所知,这只是一个随机问题,我希望了解原因,以便将来处理此类问题