PHP浮動小数点数文字列変換のピット

1746 ワード

問題の説明
今日出勤して、技術の客服のフィードバックシステムは微信にユーザーの返金を支払うことができなくて、ヒント:“注文の金額あるいは返金の金額は前の要求と一致しないで、確認してから試してください”.
問題の調査
提供された情報に基づいてログを検索すると、確かにこのような問題が発生しています.まず注文書の支払いデータに問題がないかを調べ、次に同僚がコードを修正したかどうかを見た.コードを調べる過程で返金金額の計算がおかしいことがわかりました.phpが実現したコードの一部は以下の通りです.
refund->byOutTradeNumber(
        $order->id,
        'REFUND' . $order->id,
        $fee * 100,
        $refund_fee ? $refund_fee * 100 : $fee
    );
    ...
?>

byoutTradeNumberメソッドの3番目、4番目のパラメータの要件はint型であり、渡された$feeパラメータはstring型であり、タイプ強制変換が発生すると問題が発生する.
次の例のコードで再現します.
 $fee * 100])); // string(26) "{"fee":3279.9999999999995}"
    var_dump(json_encode(['fee' => round($fee * 100)])); // string(26) "{"fee":3279.9999999999995}"

?>

以上の結論から,byoutTradeNumberメソッドを呼び出す際にパラメータをint型に強制的に置き換えると小数部が削除され,金額の不一致が生じる.その本質的な原因は、float(32.80)がメモリに実際に格納されているのは3279.9999999999995であり、タイプのスワップ後の結果が正しくないためです.これはPHPプログラミングで特に注意が必要です.
解決策
ここまで分析すれば問題の解決は簡単で、直接コードをつけます.


ps:PHP言語にはこの問題があり、他の言語にも同様にこの問題があり、言語間の文法が異なり、プログラミング思想、プログラミング経験が通用している.個人ブログリンク:https://linjinwei.com/php/20190908081309.html