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

PHP中比较两个double变量时出现异常问题

PHP中浮点数比较结果不符合预期的原因与解决方法

问题代码

$pra        = $this->PercentualeRicaricoApplicata; // 注释显示为37
$current    = floatval($currentPercentage->RicaricoPercentuale); // 注释显示为37
$lower      = floatval($lowerPercentage->RicaricoPercentuale); // 注释显示为27
            
myecho(gettype($pra) . ' - ' .gettype($current) . ' - ' . gettype($lower));
echo '<br>pra <= current: ';var_dump($pra <= $current); 
echo '<br>pra >= current: ';var_dump($pra >= $current);
echo '<br>current >= pra: ';var_dump($current >= $pra);
echo '<br>pra <= current: ';var_dump(37.00 <= 37.00); 
echo '<br>pra > lower: ';var_dump($pra > $lower);  

执行结果

double - double - double

pra <= current: bool(false)
pra >= current: bool(true)
current >= pra: bool(false)
pra <= current: bool(true)
pra > lower: bool(true)

原因分析

这是典型的浮点数精度问题:

  • 虽然注释标注两个变量值都是37,但浮点数在二进制存储时,部分十进制数值无法被精确表示,会以近似值存储。$pra和$current实际存储的二进制浮点数可能存在极其微小的差异(比如一个是37.000000000000004,另一个是37.0),导致直接比较时出现不符合直觉的结果。
  • 直接写37.00 <= 37.00时,PHP会将两个字面量解析为同一个浮点数实例,所以比较结果为true。

解决方法

  1. 阈值比较法
    不要直接对浮点数进行相等/大小比较,而是判断两个数的差值绝对值是否小于一个极小的阈值(比如1e-9,可根据精度需求调整):

    $epsilon = 1e-9;
    // 判断 $pra <= $current
    var_dump(abs($pra - $current) <= $epsilon || $pra < $current);
    // 判断 $current >= $pra
    var_dump(abs($current - $pra) <= $epsilon || $current > $pra);
    
  2. 整数存储精确数值
    如果是百分比、货币这类需要精确计算的场景,建议将数值转换为整数存储(比如把37%存储为37,带小数的37.5%存储为375,计算时再除以10),从根源避免浮点数精度问题。

  3. 高精度数学扩展
    使用PHP的bcmath扩展进行高精度数值比较,该扩展支持任意精度的十进制运算:

    // 先将浮点数转为字符串,避免精度丢失
    var_dump(bccomp((string)$pra, (string)$current) <= 0); // 等价于 $pra <= $current
    var_dump(bccomp((string)$current, (string)$pra) >= 0); // 等价于 $current >= $pra
    

内容的提问来源于stack exchange,提问作者Fabrizio La Racca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 18:15:57