doubleの比較について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
えーや

doubleの比較について

#1

投稿記事 by えーや » 16年前

あまり重要なことではないかもしれませんが
少し悩んでしまったのでみなさんのお力をお借りしたくて質問させていただきたいと思います。

テンプレに従うと
1.自分は何がしたくて
->後述するソースから、cppにおける比較はあまり精度が信頼できないのかどうかを聞きたいです。
こういう場合はどう対処するのが妥当か(妥当というのは誤差値として極小さな値をあらかじめ加算しておくなど)
2.どう取り組んで
Visual C++ 2008 EE で作ったプログラムでdouble値の比較でおかしな部分が出てきたので
後述のサンプルコードを作ってみました。

3.トラブル
同じ値なのですが比較がうまくいっていません。

4.何が知りたいか
2番と同じくです。対処法など。

5.知識量
C++とC言語を中途半端に6年程度しています。初歩的な質問で申し訳ないです。

コード
#include"iostream"

int main()
{
	double h = 1.0;
	double v = 0.0;
	for(int i=0;i<10;i++)
		v += (double)0.1;
	printf("h:%.10lf\nv:%.10lf\n",h,v);
	if(v >= h)
		std::cout << "OK\n";
	else
		std::cout << "NG\n";
	return 0;
}
出力結果 :
h:1.0000000000
v:1.0000000000
NG

といったように同じ値なのに"vのほうが小さい"と判断されてしまいます。
比較を行なう前にきわめて小さな値(0.0000000001など)をvに足しておくと結果はvのほうが大きいと判断されます。

何かに困るというわけではないのですが
これはこちら側のミスというよりはコンパイラ側の精度が問題なのでしょうか?
よろしくお願いします(変な質問で申し訳ございません)

box

Re:doubleの比較について

#2

投稿記事 by box » 16年前

コンピュータで浮動小数点数を扱う際には誤差を生じます。
0.1を10回足し合わせたとき、「正確に」1.0になるとは限りません。
printfで出力する際、小数点以下の桁数を増やしてみると
違いがわかるかもしれません。

なお、iostreamはC++の標準ヘッダーのはずです。
#include <iostream> と書くのが一般的ではないでしょうか。
""で囲むことに違和感があります。

Ace

Re:doubleの比較について

#3

投稿記事 by Ace » 16年前

ちなみに、コンピュータの小数点数の計算の誤差についてのネタは「プログラムはなぜ動くのか」という本に載ってます。
この本で上げてある例は、0.1を100回足しても10にならない、というお話です。
立ち読みしてみるとよいかもしれません。

えーや

Re:doubleの比較について

#4

投稿記事 by えーや » 16年前

回答ありがとうございます。
やはり近似だったのですか
(やはりという言い方はあまりよくないのですが回答を得られるまで考察や実験をしていました)。

>iostream
そうですね。私も違和感を感じながら使っておりました。
アドバイスありがとうございます。今後は気をつけて直していきたいと思います。

小さな疑問でしたが回答していただいたおかげですっきりしました。
本当にありがとうございます。

MNS

Re:doubleの比較について

#5

投稿記事 by MNS » 16年前

言語というよりは、コンピュータの問題だと思います。
コンピュータで値は二進法で表すため、十進法で正確に表せる小数も、
循環小数などになってしまう場合があり、うまく表すことができません。
(0.1も二進法では無限小数になってしまいます)
これを『丸め誤差』などといったりしますが、これは演算では必ず出るものです。
例に出されているプログラムでは、10回ほど小数の足し算を行われていますが、
私の環境では、0.00000000000000011の誤差が発生しました。
ですから、例えば>=演算を行いたい時は、
if(v >= h)

if(v+(1e-10) > h)
などに変える、などの手立てがあると思います。
(1e-10は1の-10乗という意味です)

閉鎖

“C言語何でも質問掲示板” へ戻る