2

この種のループがあるとしましょう (疑似コード)

double d = 0.0
for i in 1..10 {
    d = d + 0.1
    print(d)
}

Cでprintf("%f", d)私はこれを得る:

0.100000
0.200000
0.300000
...
1.000000

C++ では、次のcout << dようになります。

0.1
0.2
...
1

JavaでSystem.out.println(d)これを取得します:

0.1
0.2
0.3 (in debug mode, I see 0.30000000000004 there but it prints 0.3)
...
0.7
0.799999999999999
0.899999999999999
0.999999999999999

だから私の質問はこれらです:

  1. この単純なコードが Java で印刷されているのに、C では正しいのはなぜですか?
  2. これは他の言語ではどのように動作しますか?
4

3 に答える 3

7

ここで回答したように、これはどの言語にも関係ありません。

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

実数は無限です。コンピュータは有限数のビット (32 ビット、現在は 64 ビット) で動作しています。その結果、コンピューターによる浮動小数点演算では、すべての実数を表すことができません。0.1 はこれらの数値の 1 つです。

これはRubyに関連する問題ではなく、すべてのプログラミング言語に関連する問題であることに注意してください。これは、コンピューターが実数を表現する方法に起因するためです。

于 2012-01-17T14:33:12.033 に答える
6

この単純なコードが Java で印刷されているのに、C では正しいのはなぜですか?

同じ操作を比較していないため、異なる結果が得られます。

の動作doubleは、ハードウェアを使用してそれぞれの場合にこれらの操作を実行するため、異なる言語間でまったく同じです。唯一の違いは、結果を表示するために選択した方法です。

Java で実行すると、

double d = 0;
for (int i = 1; i <= 10; i++)
    System.out.printf("%f%n", d += 0.1);

それは印刷します

0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
0.800000
0.900000
1.000000

あなたが実行する場合

double d = 0;
for (int i = 0; i < 8; i++) d += 0.1;
System.out.println("Summing 0.1, 8 times " + new BigDecimal(d));
System.out.println("How 0.8 is represented " + new BigDecimal(0.8));

あなたが得る

Summing 0.1, 8 times 0.79999999999999993338661852249060757458209991455078125
How 0.8 is represented 0.8000000000000000444089209850062616169452667236328125
于 2012-01-17T14:29:19.217 に答える
2
  1. 印刷ルーチンの動作方法が原因です。0.1バイナリ浮動小数点形式で正確に表すことはできません。
  2. Pythonの場合:

    >>> print('%.20f' % (.1 * 8))
    0.80000000000000004441
    >>> d = .0
    >>> for i in xrange(10):
    ...  d += .1
    ...  print('%.20f' % d)
    ... 
    0.10000000000000000555
    0.20000000000000001110
    0.30000000000000004441
    0.40000000000000002220
    0.50000000000000000000
    0.59999999999999997780
    0.69999999999999995559
    0.79999999999999993339
    0.89999999999999991118
    0.99999999999999988898
    

    ただし、注意してください。

    >>> print('%.20f' % .8)
    0.80000000000000004441
    
于 2012-01-17T14:28:04.187 に答える