JDK 8和JDK 13之间浮点数的差异

10
似乎JDK 8和JDK 13的浮点数有所不同。
我在JDK 8上使用Math函数:
cos(2.3) = -0.666276021279824

在JDK 13上:

cos(2.3) = -0.6662760212798241

这是如何发生的?在使用 Windows 10 的第11代英特尔和 AMD Ryzen 上,存在差异。

2022年3月20日编辑:
使用 Long.toHexString(Double.doubleToRawLongBits()),我得到不同的位模式:
在JDK 8上我得到:

cos(2.3) = 0xbfe5522217302fe0

我使用JDK 13:

cos(2.3) = 0xbfe5522217302fe1

3
你是怎样展示这些数字的? - Shawn
我正在使用 Double.toString() 来显示结果。 - Rúben Dias
请将详细信息添加为问题的编辑,而不是作为评论。 - Basil Bourque
2
如果您使用StrictMath会发生什么? - Louis Wasserman
使用StrictMath,JDK 13的结果与JDK 8的结果相匹配。好的。 - Rúben Dias
1
说实话,使用任意精度的库,我们可以展示最接近 2.3 的双精度数的确切余弦值如下...302fe09b9492... 因此,确切值在两者之间,更接近 JDK 13 的输出。 - aka.nice
1个回答

5
这似乎是由于JVM内置函数Math.cos引起的,这在相关问题JDK-8242461中有所描述。在那里经历的行为并不被认为是一个问题:

在此错误报告中返回的结果确实是相邻的浮点值 [这也是本例的情况]

[...]

因此,虽然可能有一个或另一个返回值超出了准确度范围,但仅仅是对Math.cos有不同的返回值本身并不能证明存在问题。

要获得可重复的结果,请使用StrictMath.cos。

事实上,通过使用-XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_dcos(如链接问题中提议的)禁用内置函数,Math.cos会产生与StrictMath.cos相同(预期)的结果。
因此,看起来您在这里看到的行为很可能也符合Math文档的规定。

此外,我的(非专业)猜测是Java 8和13之间的差异可能来自于JDK-8143353,该问题改变了sincos内在函数。 - Marcono1234

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接