web-dev-qa-db-ja.com

浮動小数点/丸め誤差の簡単な例は何ですか?

浮動小数点変数を使用すると「エラー」と聞いたことがあります。今私はこのパズルを解こうとしています、そして私はいくつかの丸め/浮動小数点エラーを受け取っていると思います。だから私は最終的に浮動小数点エラーの基本を理解するつもりです。

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

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

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

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

31
MrDatabase

絵は千の言葉に値する-方程式f(k)を描いてみてください:
enter image description here
そして、そのようなXYグラフが表示されます(XとYは対数スケールです)。
enter image description here
コンピュータが丸め誤差なしで32ビットの浮動小数点数を表すことができる場合、kごとにゼロを取得する必要があります。ただし、浮動小数点誤差の累積により、kの値が大きくなると誤差が増加します。

ああ!

31
 for(double d = 0; d != 0.3; d += 0.1); // never terminates 
29
Motti

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

整数は、右端のビットが1で格納され、左側の各ビットは2倍(2、4、8、...)です。これが2 ^ nまでの整数を格納できることは簡単です。ここで、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
>>> 

フロートとダブルを使用した等価テストでは、どの言語を使用していても十分に注意する必要があります。

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

12

しばらく前に私を捕まえたシンプルなCの1つ、

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

>> 90.0999

これは、DMSの角度をラジアンに変換する関数にありましたが、上記の場合はそうではありませんでした。

6
SmacL

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

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

ダブルスとフロート..

3
Rory O'Bryan

私はPythonインタプリタからこれを好きです:

Python 2.7.10 (default, Oct  6 2017, 22:29:07) 
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1+0.2
0.30000000000000004
>>>
2
Samuel Li

超シンプル:

a = 10000000.1
b = 1/10
print(a - b == 10000000)
print ('a:{0:.20f}\nb:{1:.20f}'.format(a, b))

(プラットフォームに応じて)次のように出力します。

False                                                                                                                                 
a:10000000.09999999962747097015                                                                                                       
b:0.10000000000000000555 
0
formiaczek