浮動小数点数の表示方法

浮動小数点数を正確に表示するにはどうしたらいいんだろう。3番目のprintfで1と表示されるのが困る。値としては1ではない値が入っているわけなのだから、なにかそれのわかる出力方法はないのか。このケースに関しては2番目のように%.17lfでそれなりに表示できるけど、それって小数部の頭に0がいくつあるかわからないシチュエーションでは使えないわけで。むー。

#include <stdio.h>
#include <math.h>
int main(){
  double p = 1.0 / 6.0;
  double sum = 0.0;
  int i;
  for(i=0; i<6; i++){
    sum += p;
  }

  printf("%lf\n", sum); // -> 1.000000
  printf("%.17lf\n", sum); // -> 0.99999999999999989
  printf("%g\n", sum); // -> 1
  sum -= 1;
  printf("%lf\n", sum); // -> -0.000000
  printf("%g\n", sum); // -> -1.11022e-16
}

仕方がないから仮数部をそのまま表示する関数を作ろうとしていたらnyaxtがさくっと作ってくれた。ありがとう!
http://websvn.nyaxtstep.com/viewvc.cgi/sandpit/c/ieee754/ieee754.c?view=markup

今、もっと初心者に優しい表示方法にしようとしていじっていてバグが発覚したところ。少々お待ちください。


むー、わけがわからない。

  // mantissa -> char*
  char smant[52];
  uint64_t m = mantissa - 1;
  printf("m: %lld\n", m);
  for(j=0; j<52; j++){
    m *= 10;
    smant[j] = '0' + (m >> 52);
    //printf("%lld\n",  (m >> 52));
    //printf("%lld\n",  m);
    m &= MANTISSA_MASK;
  }
  printf("smant: %s\n", smant);
-----
m: 0
smant: 00000000000000000000000000000000000000000000000000000011111111110000000000000000000000000000000000000000000000000000

なんだこの途中の1は。


あー、わかった。これcharの配列だけど\0で終わってないから文字列として表示させようとしたときによけいな物まで表示しているんだ。直した。


とりあえず実例がよくわからなかったdenormalized numberっての以外はちゃんと表示できるようになったつもり。printfにしているのをsprintfにしよう。えー、sprintfって「十分な量の文字列領域が確保されている物と仮定する」なんて仕様なのか。


strcmpはなんで一致したときに0を返すのかと思ったらcmpと同じなんだな。