質問

decimal の代わりに double (または float )を使用する3つの利点を挙げることができます:

  1. 使用するメモリが少なくなります。
  2. プロセッサが浮動小数点演算をネイティブでサポートしているため、高速化。
  3. より広い範囲の数値を表すことができます。

しかし、これらの利点は、モデリングソフトウェアに見られるような計算集約的な操作にのみ適用されるようです。もちろん、財務計算などの精度が必要な場合は、doubleを使用しないでください。したがって、" normal"で decimal の代わりに double (または float )を選択する実際的な理由はありますか。アプリケーション?

追加して編集: 素晴らしい反応をありがとう、私は彼らから学びました。

もう1つの質問:数人は、doubleが実数をより正確に表すことができると主張しました。宣言されたとき、私は彼らが通常より正確にそれらを表すと思うでしょう。しかし、浮動小数点演算を実行すると精度が(場合によっては大幅に)低下する可能性があるというのは本当ですか?

役に立ちましたか?

解決

あなたは利点を非常によくまとめていると思います。ただし、1つのポイントが欠落しています。 decimal タイプはもっと基数10 の数値を正確に表現します(通貨/財務計算で使用される数値など)。一般的に、 double タイプ少なくとも同等の精度(間違っている場合は誰かが私を修正します)と、任意の実数の速度が確実に向上します。簡単な結論は、どちらを使用するかを検討するときは、 decimal が提供する base 10 の精度が必要でない限り、常に double を使用します。

編集:

操作後の浮動小数点数の精度の低下に関する追加の質問については、これはわずかに微妙な問題です。確かに、精度(ここでは精度を表す用語として同じ意味で使用しています)は、各操作の実行後に着実に低下します。これには2つの理由があります:

  1. 特定の数値(ほとんどの場合10進数)は浮動小数点形式で真に表現できないという事実
  2. 手作業で計算を行っているかのように、丸め誤差が発生します。ただし、これらのエラーが多くの思考を正当化するほど重要であるかどうかは、コンテキスト(実行する操作の数)に大きく依存します。

すべての場合において、理論上同等である(ただし異なる計算を使用して到達した)2つの浮動小数点数を比較する場合は、ある程度の許容差(許容範囲は異なりますが、通常は非常に小さい)。

精度のエラーが発生する可能性がある特定のケースの詳細な概要については、ウィキペディアの記事。最後に、マシンレベルでの浮動小数点数/操作の詳細な(および数学的な)議論が必要な場合は、よく引用される記事 すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

他のヒント

あなたは、浮動小数点型を使用する利点にスポットを当てているようです。私はすべての場合に小数用に設計する傾向があり、プロファイラーを使用して、小数に対する操作がボトルネックまたはスローダウンを引き起こしているかどうかを知らせてくれます。そのような場合、「ダウンキャスト」します。 doubleまたはfloatにしますが、内部でのみ行い、実行される数学演算の有効桁数を制限することで精度の低下を注意深く管理します。

一般に、値が一時的な(再利用されない)場合、浮動小数点型を使用しても安全です。浮動小数点型の実際の問題は、次の3つのシナリオです。

  1. 浮動小数点値を集約しています(この場合、精度エラーは悪化します)
  2. 浮動小数点値に基づいて値を構築します(たとえば、再帰アルゴリズムの場合)
  3. 非常に多くの有効数字を使用して数学を実行しています(たとえば、 123456789.1 * .000000000000000987654321

編集

C#10進数のリファレンスドキュメント

  

10進数キーワードは、   128ビットのデータ型。に比べ   浮動小数点型、10進数型   精度が高く、小さい   に適した範囲   財務および通貨の計算。

したがって、上記のステートメントを明確にするために:

  

私はすべて小数のデザインをする傾向があります   プロファイラに頼って   小数の演算が   ボトルネックまたはスローダウンの原因。

小数が有利な業界でしか働いたことがない。物理学やグラフィックエンジンで作業している場合は、おそらく浮動小数点型(floatまたはdouble)用に設計する方がはるかに有益です。

10進数は無限に正確ではありません(プリミティブデータ型で非整数に無限の精度を表すことは不可能です)が、doubleよりはるかに正確です:

  • 10進数= 28-29の有効数字
  • double = 15-16有効数字
  • float =有効数字7桁

編集2

Konrad Rudolph のコメントに応えて、アイテム#1(上記)は間違いなく正しいです。不正確さの集約は確かに複雑になります。例については、以下のコードを参照してください。

private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;

public static void Main(string[] args)
{
    Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
    float asSingle = 0f;
    double asDouble = 0d;
    decimal asDecimal = 0M;

    for (int i = 0; i < ONE_MILLION; i++)
    {
        asSingle += THREE_FIFTHS;
        asDouble += THREE_FIFTHS;
        asDecimal += (decimal) THREE_FIFTHS;
    }
    Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
    Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
    Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
    Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
    Console.ReadLine();
}

これにより、次が出力されます。

Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000

ご覧のとおり、同じソース定数から加算しているにもかかわらず、doubleの結果は精度が低く(おそらく正しく丸められますが)、floatの精度ははるかに低くなります。有効数字を2桁に減らしました。

ベース10の値には10進数を使用します。他の人が示唆しているように、財務計算。

ただし、doubleは一般に任意の計算値に対してより正確です。

たとえば、ポートフォリオの各ラインのウェイトを計算する場合は、結果がほぼ100%になるため、doubleを使用します。

次の例では、doubleResultはdecimalResultより1に近いです。

// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;

では、ポートフォリオの例を取り上げます:

  • ポートフォリオの各行の市場価値は金銭的価値であり、おそらく小数として最も適切に表されます。

  • ポートフォリオの各行の重み(=市場価値/ SUM(市場価値))は、通常、倍精度で表現する方が適切です。

精度が必要ない場合は、doubleまたはfloatを使用します。たとえば、私が書いたプラットフォーマーゲームでは、プレーヤーの速度を格納するためにfloatを使用しました。明らかに、画面に描画するために最終的にIntに丸めるため、ここでは超精密を必要としません。

一部の会計では、代わりにまたは組み合わせて整数型を使用する可能性を考慮してください。たとえば、操作対象のルールでは、すべての計算結果が少なくとも小数点以下6桁で繰り越され、最終結果は最も近いペニーに丸められる必要があるとしましょう。

$ 100の1/6の計算では$ 16.66666666666666 ...が得られるため、ワークシートで実行される値は$ 16.666667になります。 doubleとdecimalは、結果を小数点以下6桁まで正確に生成する必要があります。ただし、整数16666667として結果を繰り越すことにより、累積エラーを回避できます。後続の各計算は同じ精度で行い、同様に繰り越すことができます。例を続けて、その金額に対してテキサス州の消費税を計算します(16666667 * .0825 = 1375000)。 2つを追加する(短いワークシート)1666667 + 1375000 =18041667。小数点を戻すと18.041667、つまり$ 18.04になります。

この短い例ではdoubleまたはdecimalを使用した累積エラーは発生しませんが、単にdoubleまたはdecimalを計算して繰り越すだけで重大なエラーが累積する場合を示すのは非常に簡単です。あなたが操作する規則が限られた小数点以下の桁数を必要とする場合、10 ^(小数点以下の桁数が必要)を掛けて整数として各値を保存し、10 ^(小数点以下の桁数が必要)を除して実際の値を取得します値は累積エラーを回避します。

ペニーの端数が発生しない状況(自動販売機など)では、非整数型を使用する理由はまったくありません。単にドルではなくペニーを数えると考えてください。私はすべての計算がペニー全体だけを含むコードを見てきましたが、ダブルの使用はエラーにつながりました!整数のみの計算で問題が解決しました。したがって、私の型にはまらない答えは、可能であれば、2進数と10進数の両方を控えることです。

他の言語またはプラットフォームとのバイナリインターロップが必要な場合、標準化されているfloatまたはdoubleを使用する必要がある場合があります。

注:この投稿は、 http:// csharpindepthの10進数型の機能に関する情報に基づいています。 com / Articles / General / Decimal.aspx およびそれが何を意味するかについての私自身の解釈。 Doubleは通常のIEEE倍精度であると仮定します。

注2:この投稿の最小値と最大値は、数値の大きさを指します。

「10進」の長所。

  • &quot; 10進数&quot; (十分に短い)小数として記述できる正確な数値を表すことができますが、doubleはできません。これは、財務元帳で重要であり、計算を行う人間の結果が正確に一致することが重要である場合も同様です。
  • &quot; 10進数&quot;は、「double」よりもはるかに大きい仮数を持ちます。つまり、正規化された範囲内の値については、「10進数」 doubleよりもはるかに高い精度になります。

小数の短所

  • 非常に遅くなります(ベンチマークはありませんが、少なくとも1桁以上は推測するでしょう)、10進数はハードウェアアクセラレーションの恩恵を受けず、その上での計算には、累乗による比較的高価な乗算/除算が必要になります加算/減算の前に指数を一致させ、乗算/除算後に指数を範囲に戻すための10の(2の累乗による乗算と除算よりもはるかに高価です)。
  • 10進数は、ダブルウィルより早くオーバーフローします。 decimalは、&#177; 2 96 -1までの数字のみを表すことができます。比較により、doubleは最大&#177; 2 1024
  • までの数値を表すことができます
  • 10進数はより早くアンダーフローします。 10進数で表現できる最小の数値は&#177; 10 -28 です。比較により、subnromal番号がサポートされている場合、doubleは2 -149 (約10 -45 )まで、2 -126 (約10 -38 )そうでない場合。
  • decimalはdoubleの2倍のメモリを占有します。

デフォルトでは&quot; decimal&quot;を使用する必要があると思います。お金の仕事や、人間の計算と正確に一致することが重要であり、それ以外の場合はデフォルトの選択肢としてdoubleを使用する必要がある場合。

正確さよりもパフォーマンスを重視する場合は、浮動小数点を使用します。

アプリケーションの機能のタイプを選択します。財務分析のように精度が必要な場合は、質問に答えています。ただし、アプリケーションで見積もりで解決できる場合は、doubleで問題ありません。

あなたのアプリケーションは高速な計算を必要としているのですか、それとも彼はあなたに答えを提供するために世界中で常に時間を費やしているのでしょうか?本当にアプリケーションの種類に依存します。

グラフィックは空腹ですか? floatまたはdoubleで十分です。金融データ分析、流星は惑星のような精度を打ちますか?それらには少し精度が必要です:)

Decimalのバイト数は広く、doubleはCPUによってネイティブにサポートされています。 10進数は10を底とするため、10進数の計算中に10進数から2倍への変換が行われます。

For accounting - decimal
For finance - double
For heavy computation - double

.NET CLRはMath.Pow(double、double)のみをサポートしていることに留意してください。 10進数はサポートされていません。

.NET Framework 4

[SecuritySafeCritical]
public static extern double Pow(double x, double y);

double値は、その表記法が10進表示よりも短い場合、デフォルトで科学表記法にシリアル化されます。 (たとえば、.00000003は3e-8になります)10進値は科学表記法にシリアル化されることはありません。外部関係者による消費のためにシリアル化する場合、これは考慮事項である可能性があります。

必要なものによって異なります。

floatとdoubleはバイナリデータ型であるため、ラウンド数で some の難易度とエラーがあるため、たとえばdoubleは0.1から0.100000001490116に丸められ、doubleはまた、1/3を0.33333334326441に丸めます。単純に言えば、すべての実数がdouble型で正確に表現されるわけではありません

Luckily C#は、いわゆる10進浮動小数点演算もサポートしています。ここでは、数値はバイナリシステムではなく10進数システムで表されます。したがって、浮動小数点数を格納および処理するとき、10進浮動小数点演算は精度を失わない。これにより、高レベルの精度が必要な計算に非常に適しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top