利用者:Giant2007/sandbox現在多くのコンピュータやプログラミング言語がサポートしている浮動小数点数の標準であるIEEE 754には通常の 0(以下 +0 と書くの他負のゼロである -0がある。 本項では、IEEE 754における負のゼロと通常の 0との取り扱いについて述べる。 IEEE 754 の仕様策定の際、符号付きのゼロを採用するといくつかのクリティカルな問題で数値的な正確さ(accuracy)の達成が(精度(precision)ではない)容易になると主張され[1]、特に複素数の初等関数の計算が挙げられた[2]。 一方で符号付きのゼロという概念は、-0 も +0 も同じ 0 だという多くの数学の領域での前提に反している為、一部の計算において -0 の存在を忘れてプログラムを組むと、思わぬバグの原因となることがある(その例は負のゼロの項目を参照)。 正のゼロと負のゼロは算術比較演算では等しいと判定されるが、一部演算では異なる結果を生じる[3]。 表現法IEEE 754 の二進浮動小数点数では、ゼロは指数部と仮数部がゼロで表され、負のゼロの場合はさらに符号ビットが 1 となる。計算結果が負の極めて小さい値で算術アンダーフローとなった場合、負のゼロが結果として得られる。また、−1.0 * 0.0 の計算結果も負のゼロとなる。そのプログラミング言語のリテラルが対応していれば、単に IEEE 754 の十進浮動小数点数では、負のゼロの指数部は任意の正規の値で、仮数部は全てゼロであり、符号ビットが 1 で表される。 属性と操作IEEE 754 では、正のゼロと負のゼロを各種演算で使用したときの振る舞いを規定している。計算結果は丸めモードの設定に影響される。 算術標準において、その計算は無限大を含む拡張実数直線を対象としており、1/−0 = −∞ および 1/+0 = +∞ となるよう2つのゼロが存在するとみなせる。すなわちこの場合に限っては0をある種の無限小のように扱っている。標準では一般に任意の非ゼロ数のゼロ除算は、正負どちらかの無限大になる。±0/±0 に限り、NaN になる。 それ以外の乗除算は通常の符号の組み合わせと同じように扱われる。
加減算は値が相殺される場合特別に扱われる。
負のゼロが存在するため、浮動小数点数の変数 他に次のような特別規則がある。 複素数など一般に複素数などの極座標表示においては、その偏角に を加減しても複素数としては同じ値を示す、という性質がある。通常は代表値として、偏角を とすると に制限するなどするが、マイナスゼロがある場合、の偏角を とするのに対し の偏角を とする、といったように使い分ける用例がある。複素数を使わない場合でも、たとえば 比較IEEE 754 規格は、C言語やJavaの IEEE 754 では Java では、 Double negativeZero = new Double(-0.0);
negativeZero.equals(-0.0); // Result: true
negativeZero.equals( 0.0); // Result: false
以下は、後で紹介するものほどトリック的な方法となる。まず、 任意の非ゼロの値を除算して、正のゼロと負のゼロを区別できる。
型のパンニングにより、整数型としてアクセスし、ビットパターンとして比較する。C言語では、移植性のある技法ではないが(標準ではそのような操作の結果は「未定義」である。strict aliasing rule)、var が IEEE 754の単精度である場合、 *(uint32_t *)&var == 0x80000000UL
で、負のゼロかどうか比較できる。 共用体を利用すれば、このようなアクセスが標準では「処理系定義」であるので、移植性が少しはマシである。 脚注
参考文献
関連項目
|