私は広い視野を持ちたいと思っています「非正規データ」そして、それが何であるか、私が正しく理解していると思う唯一のことは、プログラマーの観点からは特に浮動小数点値に関連するものであり、CPU の観点からは一般的なコンピューティング アプローチに関連するものであるという事実です。
誰かこの2つの単語を解読してくれませんか?
編集
私が C++ アプリケーションと C++ 言語のみを対象としていることに留意してください。
ベストアンサー1
C++ についてお尋ねですが、浮動小数点値とエンコードの詳細は、C++ ではなく、浮動小数点仕様、特に IEEE 754 によって決定されます。IEEE 754 は、これまでで最も広く使用されている浮動小数点仕様であり、これを使用して回答します。
IEEE 754では、2進浮動小数点値は3つの部分でエンコードされます。符号ビットs(正の場合は0、負の場合は1)、バイアス指数e(表現された指数と固定オフセット)と仮数フィールドふ(分数部分)。通常の数の場合、これらは正確に数(−1)を表します。s• 2e−バイアス• 1.ふここで、1.ふは、「1」の後に仮数ビットを書き込むことによって形成される2進数です。(たとえば、仮数フィールドに10ビットの0010111011がある場合、仮数1.0010111011 2を表し、これは1.182617175または1211/1024です。)
バイアスは浮動小数点形式によって異なります。64 ビット IEEE 754 バイナリの場合、指数フィールドは 11 ビットで、バイアスは 1023 です。実際の指数が 0 の場合、エンコードされた指数フィールドは 1023 です。実際の指数が -2、-1、0、1、2 の場合、エンコードされた指数は 1021、1022、1023、1024、1025 です。非正規数の指数が 0 であると言う場合、エンコードされた指数が 0 であることを意味します。実際の指数は -1022 未満になります。64 ビットの場合、通常の指数間隔は -1022 ~ 1023 (エンコードされた値 1 ~ 2046) です。指数がこの間隔から外れると、特別なことが起こります。
この指数間隔を超えると、浮動小数点数は有限数を表さなくなります。エンコードされた指数 2047 (すべての 1 ビット) は、無限大を表します (仮数フィールドは 0 に設定されます)。この指数間隔を下回ると、浮動小数点数は非正規数に変わります。エンコードされた指数が 0 の場合、仮数フィールドは 0 を表します。ふ1 の代わりに。ふ。
これには重要な理由があります。最も低い指数値が通常のエンコードである場合、その仮数の下位ビットは小さすぎて、浮動小数点値として単独で表すことができません。先頭の「1.」がなければ、最初の 1 ビットがどこにあるかわかりません。たとえば、指数が最も低く、仮数が 1.0010111011 2と 1.00000000000 2である 2 つの数値があるとします。仮数を減算すると、結果は .0010111011 2になります。残念ながら、これを通常の数値として表す方法はありません。すでに最も低い指数に達しているため、この結果の最初の 1 がどこにあるかを示すために必要な下位指数を表すことができません。数学的結果は小さすぎて表すことができないため、コンピューターは最も近い表現可能な数値、つまり 0 を返すことを余儀なくされます。
これにより、浮動小数点システムで、 という望ましくない特性が生じますa != b
。a-b == 0
これを避けるために、非正規数が使用されます。非正規数を使用すると、実際の指数が減少しない特別な間隔が得られ、表現できないほど小さい数値を作成せずに演算を実行できます。エンコードされた指数が 0 の場合、実際の指数はエンコードされた指数が 1 の場合と同じですが、仮数の値は 0 に変わります。ふ1 の代わりに。ふこれを行うと、a != b
の計算値がa-b
ゼロにならないことが保証されます。
64 ビット IEEE 754 バイナリ浮動小数点のエンコードにおける値の組み合わせは次のとおりです。
サイン | 指数(e) | 有効ビット (ふ) | 意味 |
---|---|---|---|
0 | 0 | 0 | +ゼロ |
0 | 0 | ゼロ以外 | +2 −1022 •0.ふ(正常範囲外) |
0 | 1から2046 | 何でも | +2e−1023 •1.ふ(普通) |
0 | 2047 | 0 | +無限大 |
0 | 2047 | ゼロではないが上位ビットがオフ | +、NaN を示す |
0 | 2047 | ハイビットオン | +、静かなNaN |
1 | 0 | 0 | −ゼロ |
1 | 0 | ゼロ以外 | −2 −1022 •0.ふ(正常範囲外) |
1 | 1から2046 | 何でも | −2e−1023 •1.ふ(普通) |
1 | 2047 | 0 | −無限大 |
1 | 2047 | ゼロではないが上位ビットがオフ | −、NaNを通知 |
1 | 2047 | ハイビットオン | −、静かなNaN |
いくつかの注意点:
+0 と -0 は数学的には等しいですが、符号は保持されます。注意深く書かれたアプリケーションは、特定の特殊な状況でこれを利用できます。
NaN は「Not a Number」を意味します。一般的に、これは非数学的な結果またはその他のエラーが発生し、計算を破棄するか、別の方法でやり直す必要があることを意味します。通常、NaN を使用した操作では別の NaN が生成され、何かが間違っているという情報が保持されます。たとえば、3 + NaN
NaN が生成されます。シグナリング NaN は、プログラムが間違っていることを示すか、他のソフトウェア (デバッガーなど) が特別なアクションを実行できるようにするために、例外を発生させることを目的としています。クワイエット NaN は、NaN が大量のデータ セットの一部にすぎず、後で個別に処理されるか破棄される場合に、以降の結果に伝播して、大規模な計算の残りを完了できるようにすることを目的としています。
符号 + と - は NaN で保持されますが、数学的な値はありません。
通常のプログラミングでは、浮動小数点の計算の制限と動作に関する情報を提供する場合を除いて、浮動小数点エンコーディングについて気にする必要はありません。非正規数に関して特別な操作を行う必要はありません。
残念ながら、一部のプロセッサは、非正規数をゼロに変更することで IEEE 754 標準に違反したり、非正規数を使用するとパフォーマンスが非常に低下したりする点で壊れています。このようなプロセッサをプログラミングする場合は、非正規数の使用を避けるようにしてください。