为什么在 Java 中 pow(1, qNaN) 是 qNaN 而在 IEEE 754-2008 pow(1, qNaN) 中是 1?

问题描述

为什么在 Java 中 pow(1,qNaN)qNaN 而在 IEEE 754 中 pow(1,qNaN)1

Java:

System.out.println(Math.pow(1,Double.NaN)); // prints NaN (which is qNaN)

$ javac --version
javac 11.0.11

IEEE 754-2008,9.2.1 特殊值:

pow (+1,y) 对于任何 y 都是 1(即使是安静的 NaN)

解决方法

之所以这样,是因为 Math.powjavadoc 指定它是这样。它说:

public static double pow​(double a,double b)

返回第一个参数的第二个参数的幂的值。特殊情况:

  • 如果第二个参数是正零或负零,则结果为 1.0。
  • 如果第二个参数为 1.0,则结果与第一个参数相同。
  • 如果第二个参数为 NaN,则结果为 NaN。
  • ....

至于为什么以这种方式指定,我最好的建议是询问指定它的人。


更新 - 经过一些进一步的研究,我现在可以解释这种差异。

Java 发布时,IEEE 754 的发布版本是 1985 年的版本。 2008 年,发布了 754 规范的主要修订版。根据维基百科的IEEE 754-2008 page

“[第 9 条] 是新的;它推荐了 50 种运算,包括对数、幂和三角函数,这是语言标准应该定义的。

然而,Java 设计者至少早在 10 年前就设计并实现了 Java 的 Math.pow 功能,并且按照他们的想法选择了实现 NaN 行为。他们的想法与IEEE 754-2008标准委员会的想法不同。

幸运的是,IEEE 754-2008 规定第 9 条是可选的,并且不是标准一致性所必需的。因此,Java 设计人员采取了对现有 Java 开发人员干扰最小的路线,并决定不更改 pow 语义以匹配 2008 标准。 (我认为这是正确的决定。)

注意:我只是推断这个推理。 AFAIK,实际推理尚未发布。