Edited at

C/C++ printfの%lfはdouble(倍精度浮動小数点)をフル桁で表示してくれない

More than 1 year has passed since last update.

Javaのバイナリをいじっていて、floatやdoubleの格納方法が気になったので以下のようなソースコードで勉強をしていました。

int main() {

union {
double d;
float f;
unsigned char c[8];
} uni;

printf("入力:");
scanf("%lf", &uni.d);

printf("d = %lf\n", uni.d);
dump(uni.c, 8);
sdumpb(buff, uni.c, 8);
exponent = (cast_n(&uni.c[4], 4) & 0x7FF00000) >> 20;
printf("指数部:%d(%d)\t仮数部:%s\n", exponent - 1023, exponent, &buff[12]);

uni.f = uni.d;
printf("f = %f\n", uni.f);
dump(uni.c, 4);
dumpb(uni.c, 4);
sdumpb(buff, uni.c, 4);
exponent = (cast_n(&uni.c[2], 2) & 0x7F80) >> 7;
printf("指数部:%d(%d)\t仮数部:%s\n", exponent - 127, exponent, &buff[9]);

return 0;
}

ところが、scanfから入力したはずのdoubleが小数点以下6桁までしか表示されないのです。

入力:0.1234567890123456789

d = 0.123457
3f bf 9a dd 37 46 f6 5f
00111111 10111111 10011010 11011101 00110111 01000110 11110110 01011111
指数部:-4(1019) 仮数部:1111100110101101110100110111010001101111011001011111

f = 0.123457
3d fc d6 ea
00111101 11111100 11010110 11101010
指数部:-4(123) 仮数部:11111001101011011101010

これじゃ doublefloatの値を見比べたいのに比較にならないじゃないの!

ということであちこちググってみても、%lf指定すればええねん。というような答えしか無い。

最終的に以下にたどりついてスッキリ。

  IBM Knowledge Center - fprintf()、printf()、sprintf() - データのフォーマット設定と書き込み


e E f F デフォルトの precision は 6。precision が 0 または後ろに数値を伴わずに表示されたピリオドの場合は、小数点は出力されない。


つまり、小数点以下は6桁がデフォルト。

しかし以下の記載は怪しいデス。


g G すべての有効数字が出力される。


%gを指定してもVC2008のCL.exeでも、bcc32.exe(5.5と10.2)でもフル桁表示されませんでした。

gccccならちゃんと表示されるのかな。

なので結局、printfで小数点フル桁ほしい時は

printf("%.16f", value);

とかやるのがベストなようです。

冒頭のソースコードの参考元:

  浮動小数点数の内部表現(IEEE) - Wakaba Programming School