15

今日Cで試験を受けましたが、次のような質問がありました。

このプログラムの何が問題になっていますか?

for( x = .1 ; x != 1.0 ; x += .1)
    printf("%f\n", x);

私はそれを解決することができず、私は何かを書かなければならなかったので、私は.1エラーとしてマークしました。しかし、家に帰ったとき、私はこのプログラムを実行しました。x等しいと1.0無限ループに陥ったときに壊れないことがわかりました。

$ cat exam.c
#include <stdio.h>

int main(int argc, char **argv)
{
    float x;

    for(x = .1 ; x != 1.0 ; x += .1)
        printf("%f\n", x);

    return 0;
}
$ gcc exam.c -o exam
$ ./exam
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
0.800000
0.900000
1.000000 <- ?
1.100000
1.200000
1.300000
1.400000
1.500000
....

誰かがこれが起こっている理由を説明してもらえますか?

4

6 に答える 6

18

<=または<は解決策ではありません!

ループ内でのフローティングポイントの使用には問題がないわけではありません。丸め誤差が累積します。を使用しても<=、ループが適切な回数実行されない場合があります。

<=1.0 (10回)動作しますが、 <=50.0 (499回)の予想よりも1回少なく実行されます。

 for(i = 0.1 ; i <= 50.0 ; i += 0.1)
       { ... }//runs 499 times, not 500!

これは、遭遇した場合、発見するのは非常に簡単ではないかもしれない問題です。比較の前に丸める(丸め関数)と役立つ場合がありますが、確実な解決策は...

ループ内の制御変数として整数を使用します。

于 2012-11-24T16:46:09.560 に答える
17

これは宿題の典型的な質問です。

問題は、0.1をフロートに正確に格納できないことです。<=1.0をチェックしてください。

ただし、これはクトゥルフが言ったように非常に限られた範囲でのみ機能します。私はその問題を完全に見逃しました。当然のことながら、後でその値を使用intして分割することをお勧めします。

于 2012-11-24T14:38:38.030 に答える
3

ループで使用!=しないでforください。ループ変数が期待する値に達しない場合、エラーを見つけるのが非常に困難になります。常に<代わりに使用してください。

于 2012-11-24T14:40:19.677 に答える
2

これは、IEEE浮動小数点標準によるものです。ウィキペディアをチェック

0.1 + 0.2 = 0.3 => FALSE - Expected: 0.3 | Real: 0.30000000000000004

ここで実際の(JavaScript)デモをチェックしてください:http://k8.no-ip.org/stackoverflow/13542220.htm

于 2012-11-24T14:54:46.723 に答える
1

提案、ループが必要になるたびに整数を使用してください。

int x;
float y = 0;
for( x = 1; x < 11; x += 1){
    y += 0.1; 
    printf("%f\n", y);
}

または、これも使用できます。

for( x = 1; x < 11; x += 1){
    printf("%f\n", ( x / 10.0 ) );
}

どちらの場合も、ループ値を整数として保持します。

于 2012-11-24T14:56:41.263 に答える
1

0.1をフロートに正確に格納することはできません。浮動小数点数には概算値が含まれており、それを正確な値に等しくしようとしています。

于 2012-11-24T14:39:33.903 に答える