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