novaの日記: IEEE 754-1985 ふぉーまっと 1
IEEE 754-1985 フォーマットの倍精度浮動小数点数を、10進数の実数に復元するメモ
プログラムなら、対象の 8byte を double 型に突っ込めば完了。手動でシコシコやろうとすると結構手間が掛かります。
以下の hex が与えられたとします。
40 8f 40 00 00 00 00 02
コレは、1000.0000 を IEEE 754-1985 フォーマット (倍精度浮動小数点数 [64bit]) に変換したモノです。
コレを 1000.0000 に復元してみます。
まず、バイナリにします。
01000000 10001111 01000000 00000000 00000000 00000000 00000000 00000010
続いて、符号部・指数部・仮数部 に分けます。倍精度浮動小数点数 [64bit] の場合は、 上位ビットから、符号部 [1bit]、指数部 [11bit]、仮数部 [52bit] と決まっているので、
- 符号部: 0
- 指数部: 10000001000
- 仮数部: 1111010000000000000000000000000000000000000000000010
となります。符号部が 0 なら正の数、1 なら負の数です。このデータの符号部は 0 なので、正の数です。
指数部は 10000001000 なので、コレを 10進数に直すと 1032。
しかし、倍精度浮動小数点数 [64bit] の指数部は +1023 でバイアスされています。
よーするに、実際の指数に 1023 が足してあります。コレは、常に正の数にして格納する為です。
ゆえに、指数は 1032 - 1023 で 9 となります。
仮数部には暗黙の了解として、上位に 1 が付きます。コレは、仮数部の基になる数は 1 以上 2 未満であるコトが約束されている為です。
IEEE 754-1985 フォーマット にした時点で、整数部分は 1 になっているハズなので、仮数部には少数部分しか格納されていません。
つまり、本来の姿は、
1.1111010000000000000000000000000000000000000000000010
となります。そして、2 の指数階乗を掛けます。式にすると
1.1111010000000000000000000000000000000000000000000010 × 29
です。計算すると
1111101000.0000000000000000000000000000000000000000010
ですので、10進数に直すと 1000.0000... となります。
コンパイラが何をやっているか覗いてみると面白いですよ (スコア:1)
int dtoi( double f )
{
return (int)(f);
}
として、コンパイルして見ると面白い結果が得られる場合があります。
# コンパイラ依存ですが。あ、int -> double の方が余計なコードが無くて
# 判り易いかも。
なんじゃそのマジックナンバーは??!? と目を白黒することしばし…しばらく検算して「おぉっ」と思わず膝を打ちます。
私は RS/6000 用 xlc でこれを見て、3時間ほど本業を忘れてしまいました。
fjの教祖様