You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP浮点数精度导致while循环满足条件却无法进入问题排查

问题原因

这是典型的浮点数精度丢失问题:PHP和绝大多数编程语言的浮点数采用二进制存储规则,0.1、0.02这类十进制小数无法被二进制精确表示,多次加减操作后会产生肉眼不可见的微小误差。你通过echo看到的0.02是输出时自动四舍五入后的结果,实际存储的数值可能是0.0199999999999996这类略小于0.02的值,才会出现看起来满足>=0.02的判断条件、却没有进入对应循环的异常表现。

修复方案

方案1:转分单位整数运算(最稳妥)

将所有金额单位从元转换为分,全程用整数做计算,完全规避浮点数精度问题,修改后代码如下:

<?php
function leastChange($price, $payment) {
    $coins = array();
    // 转成分单位整数,加0.5是为了避免浮点数转整数时的截断误差
    $change = (int)(($payment - $price) * 100 + 0.5);
    echo ($change / 100) . "<br>";

    while ($change >= 50) {
        $change -= 50;
        $coins[] = "50c";
    }
    while ($change >= 20) {
        $change -= 20;
        $coins[] = "20c";
    }
    while ($change >= 10) {
        $change -= 10;
        $coins[] = "10c";
    }
    while ($change >= 5) {
        $change -= 5;
        $coins[] = "5c";
    }

    echo ($change / 100) . "<br>";

    while ($change >= 2) {
        echo "entered 2c with " . ($change / 100) . "<br>";
        $change -= 2;
        $coins[] = "2c";
    }
    while ($change >= 1) {
        echo "entered 1c with " . ($change / 100) . " <br>";
        $change -= 1;
        $coins[] = "1c";
    }

    foreach ($coins as $item){
        echo $item. " ";
    }
       
}

leastChange(1.98, 8);
echo '<br>';
leastChange(1.98, 5);
?>

方案2:判断加误差容忍范围

如果不想修改原有运算逻辑,可以在所有浮点数比较的地方引入一个极小的误差容忍值(也叫epsilon),抵消精度误差的影响,比如:

  • 把$change >= 0.02修改为$change >= 0.02 - 1e-8
  • 其他所有类似的浮点数比较都做相同修改即可。

内容的提问来源于stack exchange,提问作者Jake Clifford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 18:27:02