doubleとfloat
doubleとfloatは次のように呼ばれています。
double(倍精度浮動小数点型)
float(浮動小数点型)
そもそも浮動小数点型ってなんでしたっけ。
浮動小数点型
符号部(正負) + 指数部(10^) + 仮数部(数値) から構成される数値です。符号部 : 数値がマイナスかプラスかを示すための部分
指数部 : 数値の大きさを示す部分
仮数部 : 値を格納する部分
となっております。なので32bitといえども、保存できる値の領域は決まっておるわけであります。
floatとdoubleの違い
構成 | 符号部 | 指数部 | 仮数部 |
---|---|---|---|
float | 1bit | 8bit | 23bit |
double | 1bit | 11bit | 52bit |
floatは32bit(4byte),doubleは64bit(8byte)となっております。
doubleでは倍精度ということでfloatの倍のサイズを持っていることがわかります。
つまりデータとしてはdoubleのほうが2倍大きいのです。
たとえばfloatではこのように32bitの値であっても値として使える部分が
23bitと限られており、24bit目に値を入れちゃったりすると変な挙動をすることがわかります。
例えばこんな実験をしてみましょう。
int(32bit)でどんどん2進数でのbitフラグを立てていきます。24bitまで
int target{0};
for(int i = 0 ;i < 25;i++)
{
target |= 1 << i;
printf("%d\n",target);
}
printf("%f\n",(float)target);
return 0;
1
3
7
15
31
63
127
255
511
1023
2047
4095
8191
16383
32767
65535
131071
262143
524287
1048575
2097151
4194303
8388607
16777215
33554431
33554432.000000 // !! 最後の値がfloatにした瞬間変わっている
となりました。最後のintのtargetの値は33554431でしたが、これをfloatにキャスト値が変わってしまってますよね。
これはどういうことでしょうか。2進数表示に変換してみましょう
1111111111111111111111111 // <= 33554431 (24桁目まで1)
10000000000000000000000000 // <= 33554432 (25桁目のみ1)
これはどういうことでしょうか。floatでは仮数部が23bit、つまり数値として扱えるのは23bitまでなので
もともと24bitまで値が入っているintの値をキャストすると値が溢れてしまったということです。
たしかにfloatが23bitまでしか扱えないことがわかりましたね。
なので大きな値や数値の多いいbitフラグを扱う時はdoubleで行うべきであることがわかります。
doubleなら52bitまで扱えますからね。その分データは倍になってしまいますが。
普段intで32bitまで数値が扱えている分、ふとしたときにこういうワナにはまってしまわぬよう、覚えておきましょう。