クライアント側の小計計算を注文ページに追加して、ユーザーが選択するとボリューム ディスカウントが表示されるようにします。
計算の一部があちこちで 1 セントずれていることがわかりました。これは、合計が (PHP で) サーバー側で計算された最終的な合計と一致しないという事実を除けば、それほど大きな問題ではありません。
浮動小数点数を扱う場合、丸め誤差が予期される結果であることはわかっています。たとえば、149.95 * 0.15 = 22.492499999999996 および 149.95 * 0.30 = 44.98499999999999 です。前者は必要に応じてラウンドしますが、後者はそうではありません。
このトピックについて検索したところ、さまざまな議論が見つかりましたが、問題に十分に対処しているものはありません。
私の現在の計算は次のとおりです。
discount = Math.round(price * factor * 100) / 100;
一般的な提案は、ドル単位ではなくセント単位で作業することです。ただし、これには、開始数値を変換し、丸め、乗算し、結果を丸めてから元に戻す必要があります。
基本的に:
discount = Math.round(Math.round(price * 100) * Math.round(factor * 100) / 100) / 100;
四捨五入前に数値に 0.0001 を加算することを考えていました。例えば:
discount = Math.round(price * factor * 100 + 0.0001) / 100;
これは私が試したシナリオでは機能しますが、私の論理について疑問に思っています。0.0001 を追加するだけで、必要な丸め結果を強制するのに常に十分であり、多すぎることはありませんか?
注: ここでの目的のために、価格ごとに 1 回の計算のみに関心があり (したがって、エラーを複雑にすることはありません)、小数点以下 2 桁を超えて表示することは決してありません。
編集:たとえば、149.95 * 0.30 の結果を小数点以下 2 桁に丸め、44.99 を取得します。ただし、実際の結果は 44.985 ではなく 44.98499999999999 であるため、44.98 が得られます。によってエラーが発生していません/ 100
。その前に起こっています。
テスト:
alert(149.95 * 0.30); // yields 44.98499999999999
したがって:
alert(Math.round(149.95 * 0.30 * 100) / 100); // yields 44.98
乗算の実際の結果を考慮すると 44.98 が期待されますが、ユーザーが期待するものではない (そして PHP の結果とは異なる) ため、望ましくありません。
解決策: 計算を行うために、すべてを整数に変換します。受け入れられた回答が指摘しているように、元の変換計算をいくらか単純化できます。0.0001 を追加するという私の考えは、単なる汚いハックです。仕事に適したツールを使用するのが最善です。