[PHP-users 11918] Re: sprintfについて

Osamu Shigematsu php-users@php.gr.jp
Mon, 02 Dec 2002 14:21:42 +0900


重松です。こんにちは。

手元にいつも使ってる電卓がないので、
double の中身を覗いていました。

      1 #include <stdio.h>
      2
      3 int main()
      4 {
      5 >...int i;
      6 >...double d = 8.04;
      7 >...unsigned char *p = (unsigned char *) &d;
      8
      9 >...for (i = 0; i < sizeof(d); ++i)
     10 >...>...printf("%1x ", *p++);
     11
     12 >...printf("\n");
     13
     14 >...return 0;
     15 }

実行結果は、40 20 14 7a e1 47 ae 14 となりました。

うまく表現できている場合には、40 21 0 0 0 0 0 0 (これは、8.5)
のように 0 が続くはずなんですが、8.04 はそうではないですね。

ということは、つまり、double では、8.04 という値は*表現できない*
ということです。

これは、10 進数では、1/3 が何桁有効桁数があっても、
表現できないのと同じです。

PHP の浮動小数点形式は、IEEE 形式だと思いますが、
このあたりが参考になるかもしれません。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vccore/html/_core_ieee_floating.2d.point_representation_and_microsoft_languages.asp

結論として、浮動小数点形式による演算は「誤差あり」演算ですので、
結果が自分の必要な精度が確保できているか、常に気を配る必要があり、
すくなくとも、消費税の計算さえまともにできない可能性があることを
考慮する必要があります。

-- 
Osamu Shigematsu <m5issige@mr.hitachi-medical.co.jp>