#pragma twice

KAB-studio > プログラミング > #pragma twice > 228 Version 12.05 double の中身・指数部編

#pragma twice 228 Version 12.05 double の中身・指数部編

前のページへ 表紙・目次へ 次のページへ

 Version 12.05
double の中身・指数部編

「では今回はたぶんかなり難しい、 double の中身について」
『う”〜』
「まず、前回の関数でいくつか試しに出力してみます」

void Use_OutputDoubleBit()
{
    OutputDoubleBit( 1.0 );
    OutputDoubleBit( 0.1 );
    OutputDoubleBit( 0.5 );
}

00111111 11110000 00000000 00000000 00000000 00000000 00000000 
00000000 1.00000000000000000000

00111111 10111001 10011001 10011001 10011001 10011001 10011001 
10011010 0.10000000000000001000

00111111 11100000 00000000 00000000 00000000 00000000 00000000 
00000000 0.50000000000000000000

「入りきらないから改行入れてあるからね」
『一番後ろのが元の値ね。それにしても……なんか法則性全然ないね。
1.0 と 0.1 って似そうなのに全然違う』
「特に 0.1 はね。この辺が誤差が出る理由」
『やっぱり難しそう……』
「だから、ひとつひとつ見ていくね。まず、一番左側のビットについて。こ
れは符号で、プラスだと 0 、マイナスだと 1 になります」

    OutputDoubleBit(  1.0 );
    OutputDoubleBit( -1.0 );

00111111 11110000 00000000 00000000 00000000 00000000 00000000 
00000000 1.00000000000000000000
10111111 11110000 00000000 00000000 00000000 00000000 00000000 
00000000 -1.00000000000000000000

『これはわかりやすいね』
「これはね」
『う”』
「次に double の中で一番シンプルな数、 2.0 について見てみます」

    OutputDoubleBit( 2.0 );

01000000 00000000 00000000 00000000 00000000 00000000 00000000 
00000000 2.00000000000000000000

『うわ、ホントだ。ほとんどゼロ! でも 2 が一番シンプルってどういう
こと? かなり変すぎ』
「 2 が一番シンプルなのは、浮動小数点は 2 が基本になってるから。まず
は、この 2.0 を使って指数部について見てみます」
『指数部って、 10 をいくつ掛けるかってゆーのだったよね』
「そう……なんだけど、実際には 10 じゃなくて、 2 なんです」
『 2 ……?』
「上の 2.0 のを例に、指数部の部分を見てみます」

 _______ ____
01000000 00000000 00000000 00000000 00000000 00000000 00000000 
00000000 2.00000000000000000000

「 _ が付いてる部分が指数部。つまり、 2.0 の指数部は」

1000000 0000

「ってこと」
『これが 2 を…… 1 個掛けてるってこと?』
「そう、これが 2 を 1 個掛けてる場合。だから 2.0 。でも……もうひと
つ 2 を掛けて 4.0 の場合はこうなります」

 _______ ____
01000000 00010000 00000000 00000000 00000000 00000000 00000000 
00000000  4.00000000000000000000

『あ、想像と違った……』
「きっとそうだと思った。この場合の指数部は」

1000000 0001

「ってなります。同じく 8.0 の場合は」

 _______ ____
01000000 00100000 00000000 00000000 00000000 00000000 00000000 
00000000  8.00000000000000000000

「 16.0 の場合は」

 _______ ____
01000000 00110000 00000000 00000000 00000000 00000000 00000000 
00000000 16.00000000000000000000

『って、これって int とかと同じ数え方じゃない!』
「そう、まとめると」

1000000 0000 :  2.0
1000000 0001 :  4.0
1000000 0010 :  8.0
1000000 0011 : 16.0

『つまり、 2 を何個掛けるか、が int とかと同じ方法で入ってるわけね』
「だいたい合ってるかな」
『だいたい?』
「最初の 1 はなんだと思う?」
『 int だと、最初の 1 ってマイナスって意味だったよね、でもなんか違う
し……』
「これは、 1.0 、 0.5 、 0.25 を見ればわかると思うよ」

 _______ ____
00111111 11110000 00000000 00000000 00000000 00000000 00000000 
00000000 1.00000000000000000000

 _______ ____
00111111 11100000 00000000 00000000 00000000 00000000 00000000 
00000000 0.50000000000000000000

 _______ ____
00111111 11010000 00000000 00000000 00000000 00000000 00000000 
00000000 0.25000000000000000000

「これをさっきのとまとめると次のようになります」

0111111 1101 :  0.25
0111111 1110 :  0.5
0111111 1111 :  1.0
1000000 0000 :  2.0
1000000 0001 :  4.0
1000000 0010 :  8.0
1000000 0011 : 16.0

『あ、普通に増えてるだけ…… unsigned ってことね。でも……』
「 2.0 を 2 で割ったら?」
『 1.0 ……それを 2 で割ったら 0.5 、 0.5 を 2 で割ったら 0.25 !』
「そういうこと。もう少し正確に書くと」

...
0111111 1101 :  2 の -2 乗
0111111 1110 :  2 の -1 乗
0111111 1111 :  2 の  0 乗
1000000 0000 :  2 の  1 乗
1000000 0001 :  2 の  2 乗
1000000 0010 :  2 の  3 乗
1000000 0011 :  2 の  4 乗
...

「ってなります」
『そういえば 2 の 0 乗は 1 だったね』
「だから、ビット的に一番大きいのと小さいのを見てみると、こうなりま
す」

0000000 0000 :  2 の -1023 乗
...
0111111 1101 :  2 の -2 乗
0111111 1110 :  2 の -1 乗
0111111 1111 :  2 の  0 乗
1000000 0000 :  2 の  1 乗
1000000 0001 :  2 の  2 乗
1000000 0010 :  2 の  3 乗
1000000 0011 :  2 の  4 乗
...
1111111 1111 :  2 の  1023 乗

『うわ、すごい大きな数……』
「 2 の 1023 乗だと、10進数で 0 が 300 個強付くくらいの数」
『うわ……』
「だから、浮動小数点なら桁そのものについてはそれほど気にしなくていい
かな」
『 int の比じゃないわね。でも……そういう大きな桁だと、誤差が出ちゃ
うわけよね』
「ううん、今見たように 2 の乗数は絶対に誤差は出ないから」
『あ、そっか、 2 をいくつ掛けるかってだけだから、誤差とか出ないん
だ。それに 0.5 とか 0.25 とか、 2 で割っていく数も誤差は出ないね』
「そういうこと。というわけでまとめ」

・最初のビットはプラス/マイナスのフラグ。

・2番目のビットから12番目のビットは指数。
 2 の何乗か、を表している。
 unsigned int に近い形式で表現。
 ただし最初から 1023 が足された状態。

・ 2 の乗数の数は誤差が出ない。
 ... 0.125 0.25 0.5 1 2 4 8 16 ...

「こんなところかな」
『じゃ、次回は仮数部の話ね!』

/*
    Preview Next Story!
*/
『……なんか今日のだけだとそんな難しくないけど』
「ひとつずつ追っていけばね」
『いっぱい出てくるとわかんなくなる?』
「というより、ビットの並びを頭の中で数値に変換するとかすると」
『げ、それは難しそう』
「特に仮数部の計算は難しいよー」
『げげ!』
「というわけで次回」
< Version 12.06 double の中身・仮数部編 >
『につづく!』
「って言っても、頭の中で変換、なんてまず必要ないんだけど」
『……勉強する意味ないし』
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。