37

浮動小数点変数を使用する際の「エラー」について聞いたことがあります。今、私はこのパズルを解こうとしていますが、丸め/浮動小数点エラーが発生していると思います。というわけで、いよいよ浮動小数点誤差の基礎を理解していきます。

浮動小数点/丸めエラーの簡単な例は何ですか (できれば C++ で)?

編集: たとえば、成功確率 p のイベントがあるとします。このイベントを 10 回行います (p は変化せず、すべての試行は独立しています)。ちょうど 2 回の試行が成功する確率は? 私はこれを次のようにコーディングしました:

double p_2x_success = pow(1-p, (double)8) * pow(p, (double)2) * (double)choose(8, 2);

これは浮動小数点エラーの機会ですか?

4

9 に答える 9

44

百聞は一見に如かず - 方程式を描いてみてくださいf(k):
ここに画像の説明を入力
そして、このような XY グラフ (X と Y は対数スケール) が得られます。
ここに画像の説明を入力
コンピューターが丸め誤差なしで 32 ビット浮動小数点数を表すことができる場合、すべての値kが 0 になるはずです。しかし、代わりに、浮動小数点エラーの累積により、k の値が大きくなるとエラーが増加します。

ひ!

于 2011-04-17T15:49:25.687 に答える
31
 for(double d = 0; d != 0.3; d += 0.1); // never terminates 
于 2008-10-30T10:46:24.137 に答える
13

一般に、浮動小数点エラーとは、IEEE 浮動小数点表現で格納できない数値を指す場合を指します。

整数は、右端のビットが 1 で、左の各ビットがその 2 倍 (2、4、8、...) で格納されます。n がビット数である場合、これが 2^n までの任意の整数を格納できることは簡単にわかります。

浮動小数点数の仮数部 (小数部) も同様の方法で格納されますが、左から右に移動し、連続する各ビットは前の値の半分になります。(実際にはこれよりも少し複雑ですが、今のところはこれで十分です)。

したがって、0.5 (1/2) のような数値は簡単に格納できますが、1/2、1/4、1/8 などの形式の固定数の分数を加算して 1 未満のすべての数値を作成できるわけではありません。

非常に単純な例は 0.1、つまり 1/10 です。これは無限級数で行うことができます (私は実際に計算する必要はありません) が、コンピューターが 0.1 を格納するときは常に、格納されるのは正確にはこの数ではありません。

Unix マシンにアクセスできる場合は、これを簡単に確認できます。

Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1
0.10000000000000001
>>> 

どの言語を使用していても、float と double を使用した等価性テストには十分に注意する必要があります。

(あなたの例では、0.2はIEEEバイナリに格納できない厄介な数値の1つですが、p <= 0.2のように等式ではなく不等式をテストしている限り、問題ありません。)

于 2008-10-30T07:33:33.123 に答える
9

これが私を捕まえたものです:

 round(256.49999) == 256
roundf(256.49999) == 257

double と float は精度が異なるため、最初のものは として表され256.49999000000003、2 番目のものは として表され、256.5異なる方法で丸められます。

于 2014-12-17T15:37:32.583 に答える
7

少し前に私を捕まえたCの簡単な例:

double d = 0;
sscanf("90.1000", "%lf", &d);
printf("%0.4f", d);

これは印刷します90.0999

これは、DMS の角度をラジアンに変換する関数にありました。

上記の場合、なぜ機能しないのですか?

于 2008-10-30T07:52:46.127 に答える
0

Ruby のドキュメントには良い例があると思います:

sum = 0
10_000.times do
  sum = sum + 0.0001
end
print sum #=> 0.9999999999999062
于 2021-05-10T20:41:45.890 に答える