2016-08-12 60 views
5

ちょうどC#の学習を開始しました。数値解法を含む重い数学シミュレーションに使用する予定です。問題は、比較するときだけでなく、doubleを追加したり引いたりするときに精度の低下が生じることです。コードとその返信内容(コメント内)は次のとおりです。C#の倍精度精度の損失、減算の倍数を加算するときの精度の低下

namespace ex3 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      double x = 1e-20, foo = 4.0; 

      Console.WriteLine((x + foo)); // prints 4 
      Console.WriteLine((x - foo)); // prints -4 
      Console.WriteLine((x + foo)==foo); // prints True BUT THIS IS FALSE!!! 
     } 
    } 
} 

助けと説明がありがとう!

私が困惑しているのは、(x + foo)==fooです。Trueです。

+0

'=='演算子を使って浮動小数点を比較することはお勧めしません。どのように進めるべきかについては、[この投稿](https://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp)を参照してください。 –

+1

@Marceloありがとう!答えにあったリ​​ンクを投稿することができますか(浮動小数点を比較する機能)?私はそれが非常に便利だと思う。 –

+0

私のコメントにもあります。 –

答えて

4

doubleのためのMSDNの参照を見てみましょう:https://msdn.microsoft.com/en-AU/library/678hzkk9.aspx

それはdoubleが15〜16桁の精度を持っていると述べています。

数字の意味では、1e-204.0の間の差は20桁です。 1e-204.0との間で加算または減算しようとする単なる行為は、15〜16桁の精度に収まらないため、1e-20が失われたことを意味します。

したがって、doubleまでは、4.0 + 1e-20 == 4.0および4.0 - 1e-20 == 4.0です。

+0

なぜ '(x + foo)== foo'はfalseですか? OPの例では? – xr280xr

+0

@ xr280xr - そうではありません。 OPは '// prints True BUT THIS IS FALSE !!! 'というコードは'(x + foo)== foo'は 'True'を返しますが、数学的には' False'であることを意味します – Enigmativity

+0

申し訳ありません! – xr280xr

1

あなたが探しているのはおそらく小数構造(https://msdn.microsoft.com/en-us/library/system.decimal.aspx)です。 Doublesは、探している精度(C# double to decimal precision loss)でその種の値を正しく表すことはできません。その代わり、そのように、Decimalクラスを使用してみてください:

Enigmativityの答えに追加
decimal x = 1e-20M, foo = 4.0M; 

     Console.WriteLine(Decimal.Add(x, foo)); //prints 4,0000000000000000001 
     Console.WriteLine(Decimal.Add(x, -foo)); //prints -3,9999999999999999999 
     Console.WriteLine(Decimal.Add(x, foo) == foo); // prints false 
2

これは、あなたがより高い精度を必要とする作品、および28〜29桁のベースの精度でdecimalことを確認するには10:

decimal x = 1e-20m, foo = 4.0m; 
Console.WriteLine((x + foo)); // prints 4.00000000000000000001 
Console.WriteLine((x - foo)); // prints -3.99999999999999999999 
Console.WriteLine((x + foo) == foo); // prints false. 

しかし、それは小数点以下を大きく精度を持っていますが、下範囲を持っていることは事実だと注意してください。 10進数の詳細を参照here

0

これはC#では問題ありませんが、お使いのコンピュータでは問題ありません。それは実際には複雑ではないし、理解するのも難しいことではありませんが、長い間読んでいます。あなたのコンピュータの仕組みを深く知りたい場合は、this articleとお読みください。

その私見は、前述の記事より被写体までの優れたイントロはこの1つです優れTLDRサイト:

http://floating-point-gui.de/


、私は非常に簡単な説明を提供します何が起こっているのですか?あなたのアプリケーション分野は、このような知識を深く必要とするため、今後のトラブルを避けるために、少なくともそのサイトを必ず読んでください。

何が起こるかは、1e-20(1.11e-16より小さい)です。その他の数字は、コンピュータ上の倍精度のマシンのイプシロンと呼ばれます(ほとんどの場合)。マシンイプシロンよりも小さいものに1以上の数値を加算すると、その数値は四捨五入されて大きな数値に戻ります。これはIEEE 754の表現によるものです。これは、加算が行われた後、結果が「正解」(無限の精度を持つように)であることを意味します。結果は、4.00 .... 001を4に丸める制限付き/有限精度の形式で格納されます。丸めの誤差は1.11e-16より小さく、したがって許容可能であると考えられる。

+0

あなたの時間だけでなくあなたのthourough exlanationに感謝します。 2つの答えを受け入れることができれば幸いです。 –

+0

これは、コンピュータそのものとは全く関係がありません。これは、C#(および.NET)と100%関係し、フレームワーク設計者が選択した浮動小数点数表現の選択肢です。 – Enigmativity

+0

また、外部リンクで回答を提供しないでください。あなたは答えにコンテンツを入れて、あなたが書いたものをサポートするためにリンクする必要があります。 – Enigmativity