ページ 11

float変数の比較結果

Posted: 2009年10月22日(木) 19:18
by ポアンカレ
 初めて質問させて頂きます.
 以下のようなコードを作成致しましたが,変数xが
0.1であるにもかかわらず,大小関係の判定に誤りが
見られます.コーディングの理解に誤りがありましたら
ご指摘頂ければ大変助かります.

 よろしくお願い致します.

----- ココカラ -----
●ソースコード
#include <stdio.h>
main()
{
float x;
x=0.1;

printf("%d\n", x < 0.1);
printf("%d\n", x == 0.1);
printf("%d\n", x <= 0.1);
}

●実行結果
0
0
0
----- ココマデ -----

Re:float変数の比較結果

Posted: 2009年10月22日(木) 19:48
by Eeel
0.1 というのはdouble型です。
printf("%d\n", x < (float)0.1);
printf("%d\n", x == (float)0.1);
printf("%d\n", x <= (float)0.1);
として型を合わせれば正しい判定になります。
なぜdouble型とfloat型で判定が変わるのかについては、
こちらのサイトに詳しい説明がありました。

http://www.cc.kyoto-su.ac.jp/~yamada/pB/float.html

簡単に説明しますと
0.1は二進数では無限少数になります。
(1/3=0.333333・・・が3進数では0.1と表記できるように、数が無限少数であるかどうかは何進数かで変わります)
そして、double型とfloat型ではその無理数を扱う桁が違います。
ですので、0.3333 == 0.33333333 のような式になってしまい、想定通りの判定が行われない事になります。

Re:float変数の比較結果

Posted: 2009年10月22日(木) 20:01
by box
float型やdouble型のような浮動小数点数は、
ほとんどの場合誤差を伴います。
「小数」であって「少数」ではありません。

数学的には厳密に0.1であっても、
コンピュータではそうなりません。

試しに、

    printf("%.10f\n", x);

こんなコードを付け加えてみると、お使いの環境では
xが0.1よりごくわずかに大きいことがわかるでしょう。
私のところでは0.1000000015と出力しました。

なお、Eeelさんが書かれたようなキャストを行なったからといって、
xが0.1に等しいという論拠にはなりません。

xの内部表現(メモリ中の0と1のパターン)と、
float型にキャストした0.1の内部表現とが等しいというだけです。
約0.1000000015と約0.1000000015とは確かに等しいです。
しかし、0.1ではありませんね。そういうことです。

Re:float変数の比較結果

Posted: 2009年10月22日(木) 21:03
by ねこ
boxさんの言われる通り小数はビット表現では近似値となる値が大半なため誤差が出ます。

こんな風に減算結果の絶対値がある程度の値未満なら同値であるというマクロか関数を用意しておくと良いかもしれません。
#define EQUALSF( A, B ) ( ( fabs( A - B ) < 0.001 ) ? TRUE : FALSE )