私たちは最近、複数の通貨で値を処理し、それらの間で変換する必要があるシステムを実装し、いくつかのことを困難な方法で理解しました。
お金に浮動小数点数を使用しないでください
浮動小数点演算は不正確さをもたらしますが、それらは何かをめちゃくちゃにするまで気付かないかもしれません。すべての値は整数または固定10進数型として格納する必要があります。固定10進数型を使用する場合は、その型が内部で何を行うかを正確に理解してください(つまり、内部で整数または浮動小数点を使用します)タイプ)。
計算または変換を行う必要がある場合:
- 値を浮動小数点に変換する
- 新しい値を計算する
- 数値を四捨五入して整数に戻す
手順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を使用しないでください。