188

データベースに金額の値を格納するために 10 進列を使用していますが、今日はどの精度とスケールを使用するべきか疑問に思っていました。

おそらく固定幅のchar列の方が効率的であるため、10進数列についても同じことが当てはまると考えていました。それは...ですか?

また、どの精度とスケールを使用すればよいですか? 私は24時間年中無休で精度を考えていました。それはやり過ぎですか、不十分ですか、それとも大丈夫ですか?


これは私がやろうと決心したことです:

  • 換算レート (該当する場合) をトランザクション テーブル自体に float として格納します。
  • アカウント テーブルに通貨を格納する
  • 取引金額は、DECIMAL(19,4)
  • 変換率を使用するすべての計算はアプリケーションによって処理されるため、丸めの問題を制御できます

コンバージョン率の浮動小数点数はほとんどが参照用であるため、問題ではないと思います。とにかく小数にキャストします。

貴重なご意見をお寄せいただきありがとうございます。

4

10 に答える 10

207

あなたが万能を探しているなら、私はDECIMAL(19, 4)人気のある選択であることを提案します(グーグルがこれを支持します)。これは、古いVBA / Access / Jet Currencyデータ型に由来すると思います。これは、この言語で最初の固定小数点10進数型です。DecimalVB6 / VBA6 / Jet 4.0では「バージョン1.0」スタイルでのみ提供されました(つまり、完全には実装されていません)。

固定小数点の小数点以下の値を格納するための経験則は、丸めを可能にするために実際に必要な小数点以下の桁数を少なくとも1桁多く格納することです。Currencyフロントエンドの古いタイプをDECIMAL(19, 4)バックエンドのタイプにマッピングする理由の1つは、切り捨てによってCurrency丸められるのに対し、銀行家の丸めが本質的に示さDECIMAL(p, s)れることでした。

のストレージに小数点以下を追加DECIMALすると、ベンダーのデフォルトを使用するのではなく、カスタムの丸めアルゴリズムを実装できます(そして、.5で終わるすべての値がゼロから丸められることを期待している設計者にとって、銀行家の丸めは控えめに言っても憂慮すべきです) 。

はい、DECIMAL(24, 8)私にはやり過ぎのように聞こえます。ほとんどの通貨は小数点以下4桁または5桁で見積もられています。小数点以下8桁(またはそれ以上)が必要な状況は知っていますが、これは「通常の」金額(たとえば小数点以下4桁)が比例配分されている場合であり、それに応じて小数点以下の精度を下げる必要があります(これも考慮してください)。このような状況での浮動小数点型)。そして、今日、24の小数精度を要求するほど多くのお金を持っている人は誰もいません:)

ただし、万能のアプローチではなく、いくつかの調査が必要な場合があります。適用される可能性のある会計規則(GAAP、EUなど)については、設計者またはドメインの専門家に問い合わせてください。小数点以下5桁に丸めるための明示的な規則があるためDECIMAL(p, 6)、ストレージに使用するEUの州内転送を漠然と思い出します。会計士は一般的に小数点以下4桁を好むようです。


PS SQL ServerのMONEYデータ型は、移植性などの考慮事項の中でも特に、丸めの精度に重大な問題があるため、避けてください。AaronBertrandのブログを参照してください。


マイクロソフトと言語の設計者は、ハードウェアの設計者が銀行の丸めを選択したため、銀行の丸めを選択しました[引用?]。たとえば、米国電気電子学会(IEEE)規格に定められています。そして、数学者がそれを好むので、ハードウェア設計者はそれを選びました。ウィキペディアを参照してください; 言い換えると、1906年版の確率とエラー理論では、これを「コンピューターのルール」(「コンピューター」とは、計算を実行する人間を意味します)と呼ばれていました。

于 2008-10-22T08:26:49.220 に答える
114

私たちは最近、複数の通貨の値を処理し、それらの間で変換する必要があるシステムを実装しましたが、いくつかの困難な方法を見つけました。

お金に浮動小数点数を使用しないでください

浮動小数点演算は、何かを台無しにするまで気付かないかもしれない不正確さをもたらします。すべての値は整数型または固定小数点型として格納する必要があります。固定小数点型を使用する場合は、その型が内部で何をしているのかを正確に理解してください (つまり、内部で整数または浮動小数点を使用しますか?)タイプ)。

計算または変換を行う必要がある場合:

  1. 値を浮動小数点に変換する
  2. 新しい価値を計算する
  3. 数値を四捨五入して整数に戻す

手順 3 で浮動小数点数を整数に変換するときは、単純にキャストするのではなく、数学関数を使用して最初に丸めます。これは通常は になりますroundが、特殊なケースではfloorまたはになることもありますceil。違いを知って、慎重に選択してください。

値と一緒に数値の型を保存する

1 つの通貨しか扱っていない場合、これはそれほど重要ではないかもしれませんが、複数の通貨を扱う場合には重要でした。USD、GBP、JPY、EUR などの通貨には 3 文字のコードを使用しました。

状況に応じて、以下を保存することも役立つ場合があります。

  • 数値が税引前か税引後か (および税率はいくらだったか)
  • 数値が変換の結果であるかどうか (および変換元)

扱っている数値の精度限界を知る

実際の値については、通貨の最小単位と同じくらい正確にする必要があります。これは、セント、ペニー、円、フェンなどよりも小さい値がないことを意味します。それよりも高い精度の値を理由なく保存しないでください。

内部的には、より小さな値を処理することを選択できます。その場合、それは異なるタイプの通貨値です。コードでどちらがどちらであるかを認識し、混同しないようにしてください。ここでも浮動小数点値を使用しないでください。


これらのルールをすべて合わせて、次のルールに決定しました。実行中のコードでは、通貨は最小単位の整数を使用して格納されます。

class Currency {
   String code;       //  eg "USD"
   int value;         //  eg 2500
   boolean converted;
}

class Price {
   Currency grossValue;
   Currency netValue;
   Tax taxRate;
}

データベースでは、値は次の形式の文字列として格納されます。

USD:2500

$25.00 の値が格納されます。これが可能になったのは、通貨を処理するコードがデータベース層自体にある必要がないためです。したがって、すべての値を最初にメモリに変換できます。他の状況は、間違いなく他の解決策に役立つでしょう。


以前に明確にしなかった場合は、float を使用しないでください。

于 2008-10-22T12:47:39.380 に答える
2

小数点以下 4 桁で、世界最小の通貨サブユニットを正確に格納できます。マイクロペイメント (ナノペイメント?!) の精度が必要な場合は、さらに下げることができます。

私もDECIMALDBMS 固有のお金の型を好みます。そのようなロジックをアプリケーションの IMO に保持する方が安全です。同じ方針に沿った別のアプローチは、単純に [long] 整数を使用し、アプリケーション レベルで人間が読みやすいように ¤unit.subunit (¤ = 通貨記号) にフォーマットすることです。

于 2008-10-22T08:56:06.040 に答える
1

IBM Informix Dynamic Server を使用していた場合、DECIMAL または NUMERIC タイプのマイナー バリアントである MONEY タイプを使用します。これは常に固定小数点型です (一方、DECIMAL は浮動小数点型にすることができます)。1 から 32 までの位取りと 0 から 32 までの精度を指定できます (デフォルトは 16 の位取りと 2 の精度です)。したがって、保存する必要があるものに応じて、DECIMAL(16,2) を使用することもできます。これは、米国連邦赤字を最も近いセントまで保持するのに十分な大きさです。または、より狭い範囲または小数点以下の桁数を使用することもできます。

于 2008-10-22T06:05:43.933 に答える
1

場合によっては 1 セント未満にする必要があり、非常に大きなデモを使用する国際通貨があります。たとえば、トランザクションごとに 0.088 セントを顧客に請求する場合があります。私のOracleデータベースでは、列はNUMBER(20,4)として定義されています

于 2008-10-22T06:11:10.583 に答える
1

DB で何らかの算術演算 (請求レートの乗算など) を行う場合は、おそらく、ここにいる人々が提案しているよりもはるかに高い精度が必要になるでしょう。アプリケーションコードで倍精度浮動小数点値未満のものを使用したい。

于 2008-10-22T11:34:07.000 に答える
1

SQL Server の money データ型は、小数点以下 4 桁です。

SQL Server 2000 Books Online から:

金額データは、正または負の金額を表します。Microsoft® SQL Server™ 2000 では、通貨データは money および smallmoney データ型を使用して格納されます。通貨データは、小数点以下 4 桁の精度で格納できます。-922,337,203,685,477.5808 から +922,337,203,685,477.5807 の範囲の値を格納するには、money データ型を使用します (値を格納するには 8 バイトが必要です)。smallmoney データ型を使用して、-214,748.3648 ~ 214,748.3647 の範囲の値を格納します (値を格納するには 4 バイトが必要です)。より多くの小数点以下の桁数が必要な場合は、代わりに decimal データ型を使用してください。

于 2008-10-22T04:10:49.827 に答える
0

大部分の場合、あなたまたはあなたのクライアントの要件によって、使用する精度とスケールが決まると思います。たとえば、私が取り組んでいる e コマース Web サイトでは、通貨を GBP のみで扱うため、Decimal( 6, 2 ) に保つ必要がありました。

于 2008-10-22T06:16:16.893 に答える
0

ここで遅い答えですが、私は使用しました

DECIMAL(13,2)

私の考えでは、99,999,999,999.99 まで許可する必要があります。

于 2015-08-24T12:54:16.390 に答える