4

以前は型キャストがなく、反復は i=1 で停止していましたが、現在は型キャストで i=6 で停止しています。

理由はありますか?前もって感謝します!

int main(void)
{

    int i = 0;
    double d = 0.0;

    while ( (i == (int) (d * 10)) && (i < 10) )
    {
        i = i + 1;
        d = (double) (d + 0.1);
        printf("%d %lf\n", i, d);
    }

    printf("%d %lf\n", i, d);

    getch();

    return 0;
}
4

3 に答える 3

4

浮動小数点演算は不正確です。値0.1は、バイナリ浮動小数点で正確に表現できるわけではありません。ここでの推奨読書は次のとおりです。すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

プログラムのある時点で、丸め誤差によるものdよりもわずかに少なくなるため、ループは終了します。i/10

于 2012-09-06T14:01:12.390 に答える
2

i == (d * 10)他の回答に加えて、なぜループが よりも条件で早く終了するのかという質問に答えたいと思いますi == (int) (d * 10)

最初のケースでintは、 の左側の値==が 2 倍に昇格されるため、累積誤差がd*10正または負の場合 (0.999999 または 1.000001 など) に不等式が発生します。

2 番目のケースでは、右側が int に切り捨てられるため、不等式はエラーが負の場合 (たとえば 5.999999) にのみ発生します。したがって、最初のバージョンは以前に失敗します。

于 2012-09-06T14:13:56.663 に答える
1

以前に何度も述べたように、これが機能しない理由は、2 進浮動小数点数がすべての 10 進浮動小数点 2 進数を表すことができないためです。詳細については、この非常に優れた記事をご覧ください。

すべてのプログラマーが浮動小数点演算について知っておくべきこと

さて、より実用的な面では、浮動小数点を使用して別の数値と比較する場合、ほとんどroundの場合、次のように値またはイプシロン値を使用する必要があります。

if (ABS(doubleValue - intValue) < 0.00001) // 0.00001 is a margin-of-error for floating point arithmetic
    // the two numbers are even (or close to it)
于 2012-09-06T14:06:20.627 に答える