69


21

ダブルは本当にお金に不向きですか?

私はいつもc#でdouble型の変数はお金には適していないと言っています。 すべての奇妙なことが起こり得ます。 しかし、これらの問題のいくつかを示すための例を作成することはできません。 そのような例を誰かが提供できますか?

(編集。この投稿はもともとC#とタグ付けされていました。いくつかの回答は、 `decimal`の特定の詳細を参照しています。 `])。

(編集2:私は特定のc#コードを要求していたので、これは言語にとらわれないとは思わない)

8 Answer


115


とても、とても不適切です。 10進数を使用してください。

二重x = 3.65、y = 0.05、z = 3.7。 Console.WriteLine((x y)== z); // false

(Jonのページ hereからの例 - 推奨される読み方;-p)


34


四捨五入によって効果的に引き起こされる奇妙なエラーが発生します。 さらに、正確な値との比較は非常に難しいです。実際には、実際の値が特定の値に「近い」ことを確認するために、ある種のイプシロンを適用する必要があります。

具体的な例は次のとおりです。

システムを使用する。

クラスTest {static void Main(){double x = 0.1;} double y = x x x。 Console.WriteLine(y == 0.3); // Falseを出力します}}


7


はい、それは不適切です。

もしdoubleに17の有効数字があることを正しく覚えていれば、通常丸め誤差は小数点のはるか後ろに起こります。 ほとんどの金融ソフトウェアでは小数点以下4桁が使用されているため、13桁が使用可能になるため、単一の操作で使用できる最大数は、米国の国債よりもはるかに大きくなります。 しかし、丸め誤差は時間がたつにつれて累積します。 あなたのソフトウェアが長時間実行されている場合は、最終的にセントを失うことになります。 特定の操作はこれを悪化させます。 たとえば、少量から少量を追加すると、精度が大幅に低下します。

あなたはマネーオペレーションのために固定小数点データ型を必要とします、あなたがあちこちでセントを失うなら大部分の人々は気にしませんが、会計士は大部分の人々のようではありません..

*編集*このサイトによるとhttp://msdn.microsoft.com/en-us/library/678hzkk9.aspx倍精度は実際に17の代わりに15から16の有効数字を持っています。

@ Jon Skeetの10進数は、精度が高いため(28桁または29桁の有効桁数)、doubleよりも適しています。 つまり、累積丸め誤差が大きくなる可能性が低くなります。 Boojumの言及のような固定小数点データ型(つまり、私が使ったことのあるセントまたは100分の1セントを表す整数)は、実際にはより適しています。


5


`decimal`は10の倍数のスケールファクタを使うので、0.1のような数は正確に表すことができます。 基本的に、decimal型はこれを1/10 ^ 1として表しますが、 `double 'はこれを104857/2 ^ 20(実際には_really-big-number_ / 2 ^ 1023のようになります)として表します。

`decimal`は最大28/29の有効数字(0.1のような)で任意の基数10の値を正確に表すことができます。 「ダブル」はできません。


4


私の理解するところでは、ほとんどの金融システムは通貨を整数で表現しています - つまり、すべてをセントで数えています。

IEEE倍精度は、実際には-2 ^ 53から2 ^ 53までの範囲のすべての整数を表すことができます。 (ハッカーの喜び、pg。 262)あなたが足し算、引き算、掛け算だけを使用して、そしてこの範囲内の整数にすべてを保つならば、あなたは精度の損失を見るべきではありません。 しかし、分割やもっと複雑な操作には用心深くなりたいです。


2


自分のしていることがわからないときにdoubleを使うのは不適切です。

"double"は、1/90セントの誤差で1兆ドルの額を表すことができます。 だからあなたは非常に正確な結果を得るでしょう。 人を火星に乗せて生き返らせるのにかかる費用を計算したいですか。 二重はちょうどうまくいくでしょう。

しかしお金を使うと、ある計算はある結果を与えなければならず、他のものは与えないという非常に具体的な規則がしばしばあります。 $ 98.135に非常に近い金額を計算すると、結果が$ 98.14と$ 98.13のどちらであるかを決定する規則がよくあります。その規則に従って、必要な結果を得る必要があります。

あなたの住んでいる場所にもよりますが、セントやペニー、コペックを表すために64ビット整数を使うこと、あるいはあなたの国で最も小さい単位であれば何でも大丈夫です。 たとえば、セントを表す64ビット符号付き整数は、最大92,223兆ドルまでの値を表すことができます。 32ビット整数は通常不適切です。


0


ダブルに丸め誤差があるわけではありません。オンの場合は "decimal"を使用してください。 .Net…​


-4


実際には、浮動小数点* double *は、適切な単位を選択する限り、金額を表すのに最適です。

固定小数点もそうです。 どちらも8バイトを消費し、* decimal *アイテムが消費する16よりも確実に望ましいです。

何かがうまくいったかどうか 期待どおりの正しい結果が得られます)投票や個人の好みの問題ではありません。 テクニックは機能するかしないかのどちらかです。