IEEE 754における負のゼロ

現在多くのコンピュータやプログラミング言語が採用している浮動小数点数の標準であるIEEE 754には通常の 0（以下 +0 と書く)の他に負のゼロである −0がある。本項では、IEEE 754における負のゼロと通常の 0との取り扱いについて述べる。
IEEE 754 の仕様策定の際、符号付きのゼロを採用するといくつかのクリティカルな問題で数値的な正確さ（accuracy）の達成が（精度（precision）ではない）容易になると主張され、特に複素数の初等関数の計算が挙げられた。
正のゼロと負のゼロは算術比較演算では等しいと判定されるが、一部演算では異なる結果を生じる（「ビットパターンが異なるため」ではない。#複素数などの節を参照のこと）。
表現.
IEEE 754 の二進浮動小数点数では、ゼロは指数部と仮数部がゼロで表され、負のゼロの場合はさらに符号ビットが 1 となる。計算結果が負の極めて小さい値で算術アンダーフローとなった場合、負のゼロが結果として得られる。また、−1.0 * 0.0 の計算結果も負のゼロとなる。そのプログラミング言語のリテラルが対応していれば、単に codice_1 と記述しても負のゼロになる。
IEEE 754 の十進浮動小数点数では、負のゼロの指数部は任意の正規の値で、仮数部は全てゼロであり、符号ビットが 1 で表される。
属性と操作.
IEEE 754 では、正のゼロと負のゼロを各種演算で使用したときの振る舞いを規定している。計算結果は丸めモードの設定に影響される。
算術.
標準において、その計算は正と負の無限大を含む拡大実数を対象としており、1/−0 = −∞ および 1/+0 = +∞ となるような2つのゼロが存在する。すなわちこの場合に限っては0をある種の無限小のように扱っている。標準では一般に任意の非ゼロ数のゼロ除算は、正負どちらかの無限大になり、ゼロのゼロ除算は NaN になる。
それ以外の乗除算は通常の符号の組み合わせと同じように扱われる。
加減算は値が相殺される場合特別に扱われる。
負のゼロが存在するため、浮動小数点数の変数 codice_2、codice_3、codice_4 を使った式 codice_5 や codice_6 を codice_7 と最適化することはできない。
他に次のような特別規則がある。
複素数など.
一般に複素数などの極座標表示においては、その偏角に formula_16 を加減しても複素数としては同じ値を示す、という性質がある。通常は代表値として、偏角を formula_17 とすると formula_18 に制限するなどするが、マイナスゼロがある場合、formula_19の偏角を formula_20 とするのに対し formula_21の偏角を formula_22 とする、といったように使い分ける用例がある。複素数を使わない場合でも、たとえば codice_8 が formula_22 になる実装がある。
比較.
標準では、C言語やJavaの codice_9 演算子のような通常の（数値としての）比較では、負のゼロと正のゼロは等しいと判定されることとしている。
特に負のゼロのみの判定が可能な API としては、IEEE 754 の中では、codice_10 関数で、ゼロの符号をゼロでない何らかの数にコピーすることで正負を明確化することができる。C言語ではC99で標準となった。Java では、codice_11 クラスでの equals メソッドは負のゼロと正のゼロを区別する。例えば、
Double negativeZero = new Double(-0.0);
negativeZero.equals(-0.0); // Result: true
negativeZero.equals( 0.0); // Result: false
以下は、後で紹介するものほどトリック的な方法となる。まず、codice_12 のように普通に型キャストすると、負のゼロのない2の補数表現の整数では単なるゼロになってしまうので比較できない。
任意の非ゼロの値を除算して、正のゼロと負のゼロを区別できる。
により、整数型としてアクセスし、ビットパターンとして比較する。C言語では、可搬（portable）な技法ではないが（標準ではそのような操作の結果は「未定義」である。strict aliasing rule）、var が IEEE 754の単精度である場合、
で、負のゼロかどうか比較できる。
共用体を利用すれば、このようなアクセスが標準では「処理系定義」であるので、可搬性（portability）が少しはマシである。