8

これが何度も議論されていることは知っていますが、ダブルスの1ステップ除算の最も単純な例でさえ、C#で期待される、丸められていない結果をもたらすようには思えないので、おそらくつまり、コンパイラフラグなど、私が考えていない奇妙なものがあります。この例を考えてみましょう。

double v1 = 0.7;
double v2 = 0.025;
double result = v1 / v2;

最後の行を中断してVSデバッガーで調べると、「result」の値は27.999999999999996です。「10進数」に変更することで解決できることは承知していますが、周辺のプログラムでは解決できません。このような2つの低精度のdoubleが正しい値の28に分割できないのは不思議ではありませんか?本当にMath.Roundの結果に対する唯一の解決策はありますか?

4

6 に答える 6

19

このような2つの低精度のdoubleが正しい値の28に分割できないのは不思議ではありませんか?

いいえ、そうではありません。0.7も0.025も、doubleタイプで正確に表すことはできません。関連する正確な値は次のとおりです。

0.6999999999999999555910790149937383830547332763671875
0.025000000000000001387778780781445675529539585113525390625

、あなたは除算が正確に28を与えていないことに驚いていますか?ガベージイン、ガベージアウト...

あなたが言うように、 10進数を正確に表す正しい結果は、を使用することdecimalです。プログラムの残りの部分が間違ったタイプを使用している場合、それは、間違った答えを得るコスト、またはプログラム全体を変更するコストのどちらが高いかを判断する必要があることを意味します。

于 2012-05-04T07:20:44.890 に答える
6

floatまたはを扱っている場合、精度は常に問題ですdouble

コンピュータサイエンスでの既知の問題であり、すべてのプログラミング言語が影響を受けます。主に丸めに関連するこれらの種類のエラーを最小限に抑えるために、数値解析の完全なフィールドがそれに専念しています。

たとえば、次のコードを考えてみましょう。

あなたは何を期待しますか?

あなたは答えがであると期待するでしょう1、しかしこれはそうではありません、あなたは得るでしょう0.9999907

        float v = .001f;            
        float sum = 0;
        for (int i = 0; i < 1000; i++ )
        {
            sum += v;
        }
于 2012-05-04T07:37:47.930 に答える
4

double数字がどれほど「単純」または「小さい」かとは関係ありません。厳密に言えば、どちらも、0.7または0.025正確にそれらの数値としてコンピュータのメモリに保存されない可能性があるため、それらに対して計算を実行すると、高精度を求めている場合に興味深い結果が得られる可能性があります。

そうです、使用するdecimalか丸めます。

于 2012-05-04T07:20:51.583 に答える
4

これを類推して説明するには:

基数3で作業していると想像してください。基数3では、0.1は(10進数で)1/3、つまり0.333333333'です。

したがって、基数3で1/3(10進数)を正確に表すことができますが、10進数で表現しようとすると、丸め誤差が発生します。

ええと、いくつかの10進数でまったく同じことを得ることができます。それらは、10進数で正確に表現できますが、2進数で正確に表現することはできません。したがって、それらで丸め誤差が発生します。

于 2012-05-04T07:58:12.470 に答える
2

あなたの最初の質問への短い答え:いいえ、それは奇妙ではありません。浮動小数点数は実数の離散近似です。つまり、算術演算を実行すると、丸め誤差が伝播してスケーリングされます。

数値解析と呼ばれる数学の全分野があり、基本的にそのような近似で作業するときの誤差を最小限に抑える方法を扱います。

于 2012-05-04T07:21:44.347 に答える
2

これは通常の浮動小数点の不正確さです。すべての数値をdoubleとして表すことができるわけではなく、これらのマイナーな表現の不正確さは合計されます。これは、倍精度浮動小数点数を正確な数値と比較してはならない理由でもあります。私はちょうどそれをテストし、result.ToString()示しました28(多分ある種の丸めがdouble.ToString()?で起こります)。result == 28しかし戻っfalseた。そして(int)result戻っ27た。したがって、そのような不正確さを期待する必要があります。

于 2012-05-04T07:22:13.637 に答える