LoginSignup
12
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-07-31

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

12
4
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4