2017-02-21 2 views
-1

私はfinancial .netアプリケーションをサポートしています。財布にデータ型を使用するには、多くのアドバイスがあります。10進数vs doubleもう一度

は今、私はこれで立ち往生しています:

decimal price = 1.0m/12.0m; 
decimal quantity = 2637.18m; 
decimal result = price * quantity; //results in 219.76499999999999999999999991 

問題は私達の顧客を充電するための正しい値は219.77(ラウンド機能、MidpointRounding.AwayFromZero)とない219.76であるということです。

double price = 1.0/12.0; 
double quantity = 2637.18; 
double result = price * quantity; //results in 219.765 

は私が倍増するすべてのものを変更しなければならない。私は倍増するすべてのものを変更した場合

は、それが動作しているようですか?分数には他の問題がありますか?

私はより正確なデータ型を持つ結果小数点がどのダブルデータ型で結果よりも(上記のサンプルでは)それほど正確である理由、それは本当に私に説明していないので、この質問はDifference between decimal, float and double in .NET?異なっていると思いますより少ないバイトを使用します。

+2

[.NETの10進数、浮動小数点数、および倍精度の違い]の可能な複製?(http://stackoverflow.com/questions/618535/difference-between-decimal-float-and-double-in-net) –

+7

ちょうどあなたが12本の指で数えない限り、計算の基本的な欠陥、1/12は決して完璧な結果をもたらしません。どのような種類の会社が、顧客に1ドルの12分の1アイテムを請求しているのですか?まず、単価を正しく取得する必要があります。 –

+1

「私はすべてを二重に変えなければなりませんか」 - なぜですか? Hansが指摘しているように、単価を表現するのが容易ではない奇妙な出発点がありますが、その点を指摘したいと思います。とにかくあなたのユニットを細分することができるので、ユニット単価ではありません)。あなたの数量のより良い表現*を選ぶ方が良いでしょう。そうでない可能性があるので、 'decimal'が適合し、' double'が間違った結果を生成する等しく反対の例を見つけることが可能です。 –

答えて

4

ノンリピート小数点として表現できるすべての数値を10進数で正確に表すことができるようにすることをお勧めします。現実世界のお金の単位は、常に非繰り返しの小数です。あなたの問題は、あなたの価格が何らかの理由で、反復しない小数では表現できないということです。それは0.083333333...です。ダブルを使用することは実際には精度の面では役に立ちません - ダブルは正確に1/12を表すことはできません。この場合、正確さの欠如は問題を引き起こすのではなく、他の問題を引き起こす可能性があります。

さらに重要なことに、ダブルを使用すると、完全に正確に表現できなかった数字がさらに多くなります。たとえば、0.01,0.02,0.03 ...うん、あなたが気にしている可能性のある数字の多くは、正確に二重として表現することはできません。

この場合、価格はどこから来るのかという問題は、本当に重要なものです。あなたがその価格をどこに保存していても、正確には1/12を格納していません。近似値をすでに格納しているか、またはその価格が実際に計算の結果であるか(または、有理数を格納する非常に珍しい数値ストレージシステムを使用していますが、これはほとんど起こりそうにありません)。

あなたが本当に欲しいのは、二重として表すことができる価格です。それがあなたが持っているものですが、あなたがそれを変更するならば(例えば、12で割って毎年の費用を得る)、できるだけ遅くその部門を行う必要があります。そして、おそらくあなたはまた、未払い残高の分割として月額費用を計算する必要があります。この最後の部分が意味するのは、毎月10ドルで月払いをしている場合、最初の月に$ 0.83を請求するということです。その後、2ヶ月目に($ 10-0.83)/ 11を請求します。これは再び0.83になります。 5ヶ月目には(10-0.83 * 4)/ 8が課せられ、現在は0.84(一度丸められた)です。その後、来月(10-0.83 * 4-0.84)/ 7などとなります。この方法では、合計料金が正しいことを保証し、複合エラーについて心配する必要はありません。

このような丸め誤差をすべて取り除くためにシステムを再設計できるかどうか、または私が示唆したように何らかの方法で緩和する必要があるかどうかを判断するのは唯一の人です。あなたの最善の策は浮動小数点数(10進数と2進数の両方)についてできることすべてを読み上げることです。

1

通常、財務計算では、乗算と除算は、特定の小数点以下の桁数に丸められます。 (ほとんどの通貨システムでは、基本的に10の金額しか使用されませんが、これらのシステムでは、ベース以外の10の金額はまれにしか発生しません)。12を値段で割ることは、必ずしもベース10番;ビジネスロジックは、その結果の小数点以下桁数を含め、その価格がどのように丸められるかを指示します。ビジネスロジックによっては、0.083333333333333333のような結果が適切でない可能性があります。