ページ 11

for の条件

Posted: 2011年7月21日(木) 11:12
by nao
独習Cの第4版のp124で質問です!
下のプログラムでforループの条件で変数を整数値に直して10より小さいというようにしているのですが、これはつまり9.9まで表示され、その後は表示されないことになりますよね?
ですが、実行結果では10.0まで表示されてしまいます。
なぜなのでしょうか?
全くわからなかったのでよければお返事もらえるとうれしいです・・・
申し訳ないです。

コード:

#include <stdio.h>

int main(void)
{
	double f;
	for(f=1.0;(int)f<10;f=f+0.1)
	printf("%f  ",f);
	
	return 0;
}

Re: for の条件

Posted: 2011年7月21日(木) 11:30
by さかまき
printf("%f %d\n",f,(int)f);
で原因がわかります

Re: for の条件

Posted: 2011年7月21日(木) 11:35
by non
コンピュータ内部では、数値を2進数で扱っていますが、0.1はピッタリした2進数に表すことができず、
循環小数になってしまいます。詳しくは浮動小数点数などで検索してください。従って、誤差が出て
いるために期待したようになりません。
試しに、
printf("%.20f ",f);
のようにして実行してみましょう。

Re: for の条件

Posted: 2011年7月21日(木) 11:42
by 沖 滉均
0.1などは2進数少数で循環小数になってしまい表示桁数を上げて表示してみると分かりますが
誤差が発生しているためですね。

「C言語 浮動小数点 誤差」辺りで検索してみると、より詳しい説明が見られると思います。

[追記]
他の作業しながらちんたら書いてたら、お二人が既に詳しく書かれていましたね^^;

Re: for の条件

Posted: 2011年7月21日(木) 15:13
by GRAM
簡単に言うと普通の電卓で(関数電卓じゃない電卓で)1/3*3が1にならないのと似たような理由です

この手の誤差を回避するのに最も簡単な方法は
加算減算を整数で行うことです

コード:

#include <stdio.h>
 
int main(void)
{
    double f;
    for(f=1.0; f<100.0;f=f+1.0)
    printf("%f  ",f/10.0);
    
    return 0;
}
ほとんどすべての環境において
doubleが1刻みで精度を保障する範囲はint型のカバーする範囲よりも大きいので、大体の場合はこれでうまくいきます
よくある感じだとint型が2進数で31桁の整数があらわせますが、double型は53桁の整数まで正確に表せます
なので具体的には±9.0 × 1015位まで整数の加算減算の正確さが保障されます。

float使った場合、精度は極端に落ちて24桁くらいになることが多く
約1677万以上の整数は正確に扱えなくなりますので要注意です。

追記:少々間違いを訂正しました

Re: for の条件

Posted: 2011年7月21日(木) 18:58
by nao
なるほど!
やはり誤差が生じてしまうのですね・・・
実際に確認する方法も教えてくださってありがとうございます!!
これでまた独習を進められます
本当に答えてくださった皆様ありがとうございました!

Re: for の条件

Posted: 2011年7月21日(木) 18:59
by nao
すいません
解決済みにしておきます!