0

IEEE-754 Float ビジュアライザー

10 進数が IEEE-754 浮動小数点数 (符号ビット、指数ビット、仮数ビット) としてどのように格納されるのか、また、0.1 のような数値が正確に格納されない理由を正確に確認してください。

Buy Me a Coffee at ko-fi.com
処理中... 0%
正規化
指数バイアスの計算
仮数ビットの拡張
完了

結果

コンピュータが保存するすべての浮動小数点数 (JavaScript 数値、C float、Python float) は、IEEE 754 に基づいて同じ方法でエンコードされます。つまり、1 つの符号ビット、指数ビットのブロック、および仮数 (小数) ビットのブロックです。単精度 (32 ビット) は、1 つの符号ビット、8 つの指数ビット、および 23 の仮数ビットを使用します。ほぼすべての言語のデフォルトの数値型の背後にある形式である倍精度 (64 ビット) は、1 つの符号ビット、11 の指数ビット、および 52 の仮数ビットを使用します。このツールは、入力した 10 進数を受け取り、ブラウザー独自の DataView/ArrayBuffer 浮動小数点エンコーダー (コードが実際に実行されるのと同じ機械) を使用していずれかの幅でエンコードし、各ビットがどの領域に属するかによって色付けします。

エンコード自体は 3 つのステップに従いますが、このツールは最後の部分だけを表示するのではなく、すべてのステップを順に実行します。まず、正規化です。数値は、2 進小数点の前に 0 以外の数字が 1 つだけある、1.仮数 × 2^指数として書き換えられます (その値に対して小さすぎる数値は、代わりに非正規化処理が行われ、暗黙の先頭の 1 はありません)。 2 番目に、指数バイアス: 指数フィールドには正と負の両方の指数を符号なしの数値として格納する必要があるため、フィールドが 2 進数で書き出される前に固定バイアス (単精度の場合は 127、倍精度の場合は 1023) が追加されます。 3 番目に、小数部の仮数は古典的な「2 で乗算し、整数部分を次のビットとして取り、余りを保持する」方法で少しずつ拡張されます。これを仮数フィールドがいっぱいになるまで繰り返し、その時点で残ったビットによって結果が切り上げられるか切り捨てられるかを決定します (IEEE-754 のデフォルト、半数から偶数への四捨五入)。

0.1 のような普通の数値が正確に保存されないのはまさにこれが理由です。 2 進数では、0.1 は繰り返しの小数 (0.0001100110011…、永遠) なので、有限の仮数では正確に保持できず、どこかで四捨五入する必要があります。 0.1 を 32 ビット浮動小数点としてエンコードし、ビットを読み戻すと、0.1 は返されません。正確に 0.100000001490116119384765625 が得られます。倍精度では処理する仮数ビットが 29 ビット多いため、丸め誤差ははるかに小さくなりますが、ゼロでもありません。64 ビット double の 0.1 は、正確に 0.1000000000000000055511151231257827021181583404541015625 です。このツールは、正確な保存値を大きな整数演算 (浮動小数点のショートカットなし) で計算するため、入力した値とハードウェアが実際に保持している値との間のギャップが隠蔽されたり近似されたりすることはありません。

特別な値は、通常のエンコーディングではなく、正確な予約されたビット パターンを取得します。ゼロと負のゼロには、すべてゼロの指数ビットと仮数ビットがあり (符号ビットのみが異なります)、±Infinity には、すべてゼロの仮数を持つすべて 1 の指数ビットがあり、NaN には、少なくとも 1 つの仮数ビットが設定されたすべて 1 の指数ビットがあります。ここにあるものはすべてブラウザ内でローカルに実行され、入力したものはどこにもアップロードされません。そのため、ここは浮動小数点のバグに対する実際の直感を構築するための安全な場所になります。なぜほぼすべてのプログラミング言語で `0.1 + 0.2 !== 0.3` なのか、グラフィックス コードの float32 テクスチャが float64 では失われる精度を失う理由、そしてなぜ金融コードでは一般的にバイナリ浮動小数点を完全に避ける必要があるのか​​、ということです。