为什么Java中的-Infinity + Infinity的平方根?

Pra*_*tik 35 java math floating-point ieee-754

我尝试了两种不同的方法来在Java中找到平方根:

Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
Run Code Online (Sandbox Code Playgroud)

为什么第二种方式不能返回预期的答案NaN(与第一种方式相同)?

Pie*_*ens 48

的NaN是为了继续进行计算时已经获得一个真正的未定义(中间)结果返回(下IEEE 754).一个无限大的,以便继续计算已发生溢出后返回.

这样的行为

Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
Run Code Online (Sandbox Code Playgroud)

指定是因为已知(容易且快速)已生成未定义的值; 完全基于论证的标志.

但是评价表达方式

Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
Run Code Online (Sandbox Code Playgroud)

遇到溢出和无效操作.然而,无效操作识别主要取决于确定第二个参数的准确程度.如果第二个参数是先前舍入操作的结果,那么它可能不完全是 0.5.因此,返回不太严重的确定,识别溢出,以避免结果对第二自变量的准确性的严重依赖.

有关IEEE 754标准背后的一些推理的其他详细信息,包括返回标志值而不是生成异常的原因,可在

每个计算机科学家应该知道的浮点运算(1991,David Goldberg),

这是附录D.

Sun Microsystems数值计算指南.

  • 好吧,如果第二个参数不完全是0.5,那么得到的无穷大的复数阶段仍然不会接近"Pi*N",所以在数学上,它仍然是无效的操作(对于R→R函数).因此,这似乎不足以解释为什么它不会产生NaN. (3认同)
  • 我发现这里的论点值得怀疑.特别是,它缺少对(a)为什么第二个论证的可能不精确性有所不同的解释(*为什么我们应该将`pow(-inf,0.5 + epsilon)`视为`inf`而不是`nan` ?),和(b)解释`-inf`的特殊之处:`pow(-10.0,y)`为*any*非整数有限`y`提供`nan`.我认为这个理由更有可能来自于`pow(-0.0,y)`的行为,保持对称性的愿望`pow(1/x,y)== 1/pow(x,y) `,以及`1/-0.0`是`-inf`的事实. (2认同)

pie*_*t.t 30

它只是按照文档中描述的那样行事Math.

用于Math.sqrt:

如果参数为NaN或小于零,则结果为NaN.

用于Math.pow:

如果

  • 第一个参数是负零,第二个参数小于零但不是有限的奇数,或者
  • 第一个参数是负无穷大,第二个参数大于零但不是有限的奇数,

然后结果是正无穷大.

至于他们为什么做出这样的设计选择 - 你将不得不问java的作者.

  • 我同意,但使用不同的方法不应该是不一致的,特别是在数学方面,必须有一个标准答案,不是吗?根据我的看法,第二种方法是返回错误答案. (5认同)
  • @Pratik:`Math.pow()`的返回值与`pow()`的C标准定义对齐.它们似乎都符合IEEE 754的操作定义,但我没有标准方便的副本.IEEE 754设计师有非常详细的理由说明为什么事情就像他们一样,尽管凡人都不能理解. (3认同)
  • 从我个人的角度来看,两者都是错误的.你应该抛出异常,而不是返回像Nan或Infinity这样的值. (2认同)