10

重複の可能性:
浮動小数点の不正確な例

double a = 0.3;
std::cout.precision(20);
std::cout << a << std::endl;

結果: 0.299999999999999889

double a, b;
a = 0.3;
b = 0;
for (char i = 1; i <= 50; i++) {
  b = b + a;
};
std::cout.precision(20);
std::cout << b << std::endl;

結果: 15.000000000000014211

だから..「a」は本来よりも小さいです。しかし、'a' を 50 回使用すると、結果は本来よりも大きくなります。

どうしてこれなの?この場合、正しい結果を得るにはどうすればよいですか?

4

5 に答える 5

18

正しい結果を得るには、この数値型で使用可能な精度よりも高い精度を設定しないでください。

#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}

ただし、そのループが 50 回ではなく 5000 回繰り返される場合、このアプローチでも累積エラーが発生します。これは、浮動小数点数がどのように機能するかです。

于 2010-05-26T00:28:34.000 に答える
15

どうしてこれなの?

浮動小数点数は 2 進数で格納されるため、0.3 は 0.01001100110011001 です... 1/3 が 0.333333 のように繰り返すことは、10 進数で繰り返されます。と書く0.3と、実際には 0.299999999999999988897769753748434595763683319091796875 (有効数字 53 桁に丸められた無限バイナリ表現) が得られます。

浮動小数点が設計されているアプリケーションでは、0.3 を正確に表現できないことは問題ではないことに注意してください。浮動小数点は、以下で使用するように設計されています。

  • 多くの場合、4 sig figs までしか測定されず、15 を超えることはありません。
  • 対数や三角関数などの超越関数は、とにかく近似するだけです。

2 進数と 10 進数の変換は、他のエラーの原因と比較してほとんど無関係です。

0.30 ドルが正確に0.30ドルを意味する金融ソフトウェアを作成している場合は、事情が異なります。この状況のた​​めに設計された 10 進算術クラスがあります。

この場合、正しい結果を得るにはどうすればよいですか?

通常、精度を有効桁数 15 桁に制限すれば、「ノイズ」桁を隠すのに十分です。実際に正確な答えが必要でない限り、これが通常は最善の方法です。

于 2010-05-26T05:33:08.067 に答える
8

コンピュータは、浮動小数点数を 10 進数ではなく 2 進数で格納します。

0.3 など、10 進数では普通に見える多くの数値は、2 進数では有限の長さを正確に表現できません。
したがって、コンパイラは0.333331⁄3.

多くの浮動小数点数を追加すると、これらの小さな差が加算され、予期しない結果が得られます。

于 2010-05-26T00:24:29.433 に答える
1

大きいか小さいかということではなく、「0.3」を正確な値として 2 進浮動小数点数内に格納することは物理的に不可能なだけです。

「正しい」結果を得る方法は、小数点以下 20 桁を表示しないことです。

于 2010-05-26T00:26:03.563 に答える
-2

「正しい」結果を得るには、試してください

ウィキペディアの任意精度算術ライブラリのリスト: http://en.wikipedia.org/wiki/Arbitrary-precision

また

http://speleotrove.com/decimal

于 2010-05-26T00:26:57.983 に答える