Javaで平方根を見つけるために2つの異なる方法を試しました。
Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
なぜ2番目の方法がNaN
(1番目の方法と同じ)である期待される答えを返さないのですか?
NaNは、真に未定義の(中間の)結果が得られたときに計算を続行するために返されます(IEEE 754の下)。 infinityは、オーバーフローが発生した後に計算を続行するために返されます。
したがって、動作
Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
未定義の値が生成されたことが既知であるため(簡単におよび迅速に)指定されます。引数の符号のみに基づいています。
ただし、式の評価
Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
オーバーフローと無効な操作の両方が発生します。ただし、無効な操作の認識は、2番目の引数の決定の精度に大きく依存します。 2番目の引数が前の丸め演算の結果である場合、exactly 0.5ではない可能性があります。したがって、2番目の引数の精度に対する結果の重大な依存を回避するために、それほど深刻ではない決定であるオーバーフローの認識が返されます。
例外を生成する代わりにフラグ値を返す理由を含む、IEEE 754標準の背後にある推論の詳細については、
すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと(1991、David Goldberg) 、
の付録D
Math
の- ドキュメント で説明されているように動作します。
ために Math.sqrt
:
引数がNaNまたはゼロより小さい場合、結果はNaNです。
ために Math.pow
:
もし
- 最初の引数が負のゼロであり、2番目の引数がゼロより小さいが有限の奇数の整数ではない、または
- 最初の引数は負の無限大であり、2番目の引数はゼロより大きいが有限の奇数の整数ではありません。
結果は正の無限大です。
彼らがなぜそのデザインを選択したのかについては、Javaの作者に尋ねる必要があります。