以前、浮動小数点数について質問したのですが、今回はフォーマットについてです。
double型のメモリ領域
面倒なので今回もdouble型に限定しますね。
#include<iostream> #include<math.h> int main(){ double x = 1.7320508075688774152212090484681539237499237060546875; int exp; double k = frexp(x, &exp); printf("%1.80lf = \n%1.80lf x 2 ^ %05d\n", x, k, exp); return 0; }
1.73205080756887741522120904846815392374992370605468750000000000000000000000000000 = 0.86602540378443870761060452423407696187496185302734375000000000000000000000000000 x 2 ^ 00001
この結果をよーーくみると変ではないでしょうか?
私の本のIEEE754の書式によりますと、以下のようになるはずです。
浮動小数点数 = (-1)^S x (1 + 仮数部) x 2^(指数-127)
つまり、最小は、1.0000 0000 0000 0000 0000 ・・・(2)x2 ^ (-1072)
仮数部の最小値は1以上になるはずです。
しかし上記のプログラムの仮数部はどうみても1から始まってないでよね?
この書式の違いは一体どういう事でしょうか?
詳しく理解できなかったのですが、先頭に1がある表記を正規化した科学記数法というそうです。
なので上記のプログラムは不正規化数ということになると思います。
不正規化数が演算の対象に出てきた場合には例外を発生させて、あとはソフトウェアで補うようにしているコンピュータが多い。
ちょっと、何が言いたいのかわからないのですが、frexp関数による書式がIEEE754のフォーマットに準拠していない理由は何でしょうか?非常に分かりにくいです。
混乱しています。
また歴史が絡む問題でしょうか?IEEE754が規定される前に作られた関数なのかな・・?と考えましたが・・・
2、誤差に関する確認事項です。
超簡単にするために、0.02568という数字を考えます。
何らかの演算の結果の仮数部の数字と考えて下さい。
この場合、
ガード桁:5
丸め桁:6
スティッキー・ビット:8
これで正しいですか?
スティッキービット = 丸め桁の右側に0でないビットがあることを示すものである。
つまり、double型の仮数部の52bitの最後の3桁に特別な名前を付けただけという事ですかね?
2番については間違いがあったらご指摘をお願いします。
「追記」
#include <iostream> #include <math.h> int main() { float value = 1.73214; int exp; float x = std::frexp(value, &exp); printf("%1.60lf = \n", value); printf("%1.60lf * 2^ %08d\n", x, exp); union { float f; int i; } a; a.f = value; printf("%f ( %08X )\n", a.f, a.i); /* ビットの列を表示します */ for (int i = 31; i >= 0; i--) { printf("%d", (a.i >> i) & 1); } printf("\n"); /* 指数部( 1ビット )、指数部( 8ビット )、仮数部( 23ビット )を取り出します */ printf("符号部 : %x\n", (a.i >> 31) & 1); printf("指数部 : %x\n", (a.i >> 23) & 0xFF); printf("仮数部 : %x\n", a.i & 0x7FFFFF); }
1.732139945030212402343750000000000000000000000000000000000000 =
0.866069972515106201171875000000000000000000000000000000000000 * 2^ 00000001
1.732140 ( 3FDDB6C3 )
00111111110111011011011011000011
符号部 : 0
指数部 : 7f
仮数部 : 5db6c3
結果はこのようになりました。
問題はここからで、
仮数部の16進数を10進数に直すと、6141635となります。
(指数部を10進数にすると127でした。)
frexp関数の仮数部とは大きく異なる値です。
そして、この6141635から0.866069972515106201171875にどうやって変換しているのかさっぱりです。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/06/20 14:45
2017/06/20 14:51 編集
2017/06/20 14:59