问题描述
为什么在 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.pow
的 javadoc 指定它是这样。它说:
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,实际推理尚未发布。