レートの精度と金額の精度は異なる
USDの結果は小数点以下2桁で表示しても、計算に使うレートにはさらに多くの桁が必要な場合があります。レートを通貨の表示形式に合わせて切り詰めると、すべての換算への入力が変わります。
例示的なEUR/USDレート1.08765でEUR 250を換算すると、丸め前はUSD 271.91250、2桁ではUSD 271.91です。レートを先に1.09へ丸めるとUSD 272.50となり、表示結果に59セントの差が出ます。
偶数丸めでちょうど中間の値を処理する
丸める値が2つの候補のちょうど中間にある場合、偶数丸めでは、残す最後の桁が偶数になる方を選びます。小数点以下2桁では、1.005は1.00、1.015は1.02になります。中間の値を常に切り上げる規則とは異なります。
これらは正確な小数の例です。中間点をわずかに上回る値や下回る値は、丸め先の2つの値から等距離ではありません。丸めモードは、書式化関数の既定値に任せず、計算方針の一部として定めてください。
小数文字列を直接解析する
Pythonのdecimalモジュールは、文字列から小数値を作成し、計算結果を指定した刻みに丸めることができます。次のローカル実行例は、小数点以下2桁への偶数丸めを使った金額計算を再現するもので、現在のレートは取得しません。
from decimal import Decimal, ROUND_HALF_EVEN, localcontext
with localcontext() as ctx:
ctx.prec = 40
amount = Decimal("250.00")
rate = Decimal("1.08765")
result = (amount * rate).quantize(
Decimal("0.01"), rounding=ROUND_HALF_EVEN
)
print(result) # 271.91通貨の最小単位を選ぶ
すべての換算先通貨に小数点以下2桁を適用しないでください。Narwhalの換算オペレーションは、換算先通貨のISO 4217最小単位を使います。例えば、ドキュメントに記載されたUSDからJPYへの換算レスポンスは、円単位の整数金額を返します。
現在の通貨メタデータまたは換算エンドポイントが返す金額を使ってください。現金額面の丸め、加盟店の表示規則、会計方針には追加要件が生じる場合があります。レート精度とは別の明示的な選択として扱ってください。
避けられる精度損失を防ぐ
小数文字列をバイナリ浮動小数点で変換すると、小数ライブラリが受け取る前に情報が失われる場合があります。API境界では元の文字列を保持し、対応する最大金額とレートに十分な作業精度を選んでください。
- 監査と再現のため、受信したレート文字列を保持してください。
- 中間の乗算や除算は作業精度で行い、最終金額を一度だけ丸めてください。
- 丸めモードと対象の刻みを指定してください。
- 表示のためだけに書式化し、書式化したラベルを計算へ戻さないでください。
同じ入力で照合する
ローカル計算の結果がNarwhalのconvertedフィールドと異なる場合は、入力金額、返されたレートの全桁、換算先通貨の最小単位、丸めモードを比較してください。結果が間違っていると判断する前に、それらを確認します。
丸めた金額を元の通貨へ戻すと、スプレッドがなくても少額の差が生じる場合があります。バッチでは各行を丸めて合計した結果が、丸めていない行を合計してから一度だけ丸めた結果と異なることもあります。アプリケーションに必要な規則を選び、一貫して記録してください。
出典・参考資料
公開日: 。最終確認日: 。

