web-dev-qa-db-ja.com

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

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

(編集;この投稿は元々C#でタグ付けされていました;一部の返信はdecimalの特定の詳細を参照しているため、 System.Decimal )。

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

69
doekman

非常に、非常に不適切です。 10進数を使用します。

double x = 3.65, y = 0.05, z = 3.7;
Console.WriteLine((x + y) == z); // false

(ジョンのページの例 ここ -推奨読書;-p)

115
Marc Gravell

丸めによって効果的に奇妙なエラーが発生します。さらに、正確な値との比較は非常にトリッキーです。通常、実際の値が特定の値に「近い」ことを確認するには、ある種のイプシロンを適用する必要があります。

具体的な例を次に示します。

using System;

class Test
{
    static void Main()
    {
        double x = 0.1;
        double y = x + x + x;
        Console.WriteLine(y == 0.3); // Prints False
    }
}
34
Jon Skeet

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

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

お金の操作には固定小数点データ型が必要です。あちこちでセントを失ってもほとんどの人は気にしませんが、会計士はほとんどの人とは異なります。

edit
このサイトによると http://msdn.Microsoft.com/en-us/library/678hzkk9.aspx Doublesの実際の有効桁数は、17ではなく15〜16です。

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

7
Mendelt

decimalは10の倍数の倍率を使用するため、0.1のような数値は正確に表すことができます。本質的に、10進数型はこれを1/10 ^ 1として表しますが、doubleは104857/2 ^ 20としてこれを表します(実際にはreally-big-number)のようになります/2 ^ 1023)。

decimalは、最大28/29の有効数字(0.1など)を使用して、10を底とする任意の値を正確に表すことができます。 doubleはできません。

5
Richard Poole

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

実際にはIEEE倍精度 できる -2 ^ 53から+ 2 ^ 53の範囲のすべての整数を正確に表します。 (Hacker's Delight、pg。262)加算、減算、乗算のみを使用し、すべてをこの範囲内の整数に保つ場合、精度の低下は見られません。ただし、除算やより複雑な操作には非常に注意が必要です。

4
Boojum

何をしているのかわからないときにdoubleを使用することは不適切です。

「double」は1セントの1/90の誤差で1兆ドルの金額を表すことができます。したがって、非常に正確な結果が得られます。火星に男を入れて生き返らせるのにかかる費用を計算してみませんか? doubleで十分です。

しかし、お金については、特定の計算が特定の結果を出さなければならず、他の結果は出さないという非常に具体的な規則がしばしばあります。 $ 98.135に非常に近い金額を計算する場合、多くの場合、結果が$ 98.14と$ 98.13のどちらであるかを決定するルールがあり、mustそのルールに従い、必要な結果を取得します。 。

住んでいる場所に応じて、セント、ペニー、コペックなど、国の最小単位である64ビット整数を使用すると、通常は問題なく動作します。たとえば、セントを表す64ビットの符号付き整数は、最大92,223兆ドルの値を表すことができます。 32ビット整数は通常不適切です。

2
gnasher729

Doubleは常に丸め誤差を持ちません。Netを使用している場合は「decimal」を使用してください...

0
Thomas Hansen