10

floatでインクリメントするループを作成していますが、次の例に示す浮動小数点演算の問題が発生しました。

for(float value = -2.0; value <= 2.0; value += 0.2)
    std::cout << value << std::endl;

出力は次のとおりです。

-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
1.46031e-07
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8

なぜ私は1.46031e-07代わりに正確に取得しているの0ですか?これが浮動小数点エラーと関係があることは知っていますが、なぜそれが起こっているのか、そしてこれを防ぐために何をすべきか(方法がある場合)を理解できません。誰かが私が理解するのに役立つ説明をする(または私にリンクを示す)ことができますか?どんな入力でも大歓迎です。ありがとう!

4

6 に答える 6

34

他の誰もが言っているように、これは実数が無限で数えられない集合であるのに対し、浮動小数点表現は有限数のビットを使用するという事実に関係しています。浮動小数点数は実数にしか近似できず、多くの単純な場合でも、その定義のために正確ではありません。これまで見てきたように、0.2実際にはそうではありませんが0.2、代わりにそれに非常に近い数です。これらをに追加するとvalue、各ステップでエラーが累積されます。

int別の方法として、反復にsを使用し、結果を分割して、必要なドメインに戻すことを試みてください。

for (int value = -20; value <= 20; value += 2) {
  std::cout << (value / 10.f) << std::endl;
}

私にとってこれは次のようになります。

-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
于 2013-02-13T18:10:23.417 に答える
9

浮動小数点の精度の低下を回避するための明確な解決策はありません。次の論文を一読することをお勧めします。すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

于 2013-02-13T17:57:42.657 に答える
8

これは、浮動小数点数には特定の離散精度しかないためです。

0.2は実際には0.2ではありませんが、内部的にはわずかに異なる数値として表されます。

それがあなたが違いを見ている理由です。

これはすべての浮動小数点計算で一般的であり、実際に回避することはできません。

于 2013-02-13T17:56:45.913 に答える
7

ループを実行しましょう。ただし、出力精度を上げます。

コード:

for(float value = -2.0; value <= 2.0; value += 0.2)
    std::cout << std::setprecision(100) << value << std::endl;

出力:

-2
-1.7999999523162841796875
-1.599999904632568359375
-1.3999998569488525390625
-1.19999980926513671875
-0.999999821186065673828125
-0.79999983310699462890625
-0.599999845027923583984375
-0.3999998569488525390625
-0.19999985396862030029296875
1.460313825418779742904007434844970703125e-07
0.20000015199184417724609375
0.400000154972076416015625
0.6000001430511474609375
0.800000131130218505859375
1.00000011920928955078125
1.20000016689300537109375
1.40000021457672119140625
1.60000026226043701171875
1.80000030994415283203125
于 2013-02-13T18:18:31.347 に答える
6

整数を使用して分割します。

for(int value = -20; value <= 20; value += 2)
    std::cout << (value/10.0) << std::endl;
于 2013-02-13T18:07:06.033 に答える
1

いくつかのアルゴリズムの本またはインターネットの使用による浮動小数点表現について学びます。そこにはたくさんのリソースがあります。

とりあえず、あなたが望むのは、何かがゼロに非常に近いときにゼロを取得するための何らかの方法のようです。そして、私たちがこのプロセスを「丸め」と呼んでいることは誰もが知っています。:)だから、それらの数字を印刷するときにそれを使ってみませんか。 printf関数は、これらの種類のものに優れたフォーマット能力を提供します。printfでフォーマットする方法がわからない場合は、次のリンクの表を確認してください。(数値を正しく丸めて表示するためのフォーマットを使用できます)printf ref:http ://www.cplusplus.com/reference/cstdio/printf/?kw=printf

- 編集 -

数学によると1.9999999....が2.0と同じであることを知っている人もいるかもしれません。唯一の違いは表現です。しかし、その数は同じです。

浮動小数点の問題はこれに少し似ています。(これは説明のためだけのものです。問題は1.9999 ....のものと同じではありません。)

于 2013-02-13T18:04:22.117 に答える