




array_filter直接比较浮点数会漏值,因IEEE 754导致0.1+0.2≠0.3(实际为0.30000000000000004),==/===均不可靠;应改用abs($v - 0.3) zuojiankuohaophpcn $epsilon判断。
array_filter 直接比较会漏掉“看似相等”的浮点数PHP 中浮点数无法精确表示(如 0.1 + 0.2 不等于 0.3),导致用 == 或 === 做数组筛选时,本该匹配的值被跳过。这不是 PHP 特有,而是 IEEE 754 浮点标准的共性问题。
常见错误写

$arr = [0.1 + 0.2, 0.3, 0.6 - 0.3];
$result = array_filter($arr, function($v) { return $v == 0.3; }); // 可能只返回一个元素,甚至空数组
0.1 + 0.2 实际是 0.30000000000000004,与字面量 0.3 的二进制表示不完全一致== 在浮点场景下不可靠;=== 更严格,更不可能命中round($v, 10) == round(0.3, 10) —— round() 在边界值(如 0.049999999999999996)可能四舍五入失真abs($a - $b) 替代相等判断
这是最通用、最可控的浮点容差比较方式。关键在于选对 $epsilon —— 它不是固定常量,而应根据数据量级和精度需求动态设定。
实操建议:
1e-6 到 1e-8 足够安全12.34),可设 $epsilon = 1e-3(即允许 ±0.001 偏差)0.000001,统一用科学计数法 1e-6,更易读且无类型歧义$target = 0.3;
$epsilon = 1e-8;
$result = array_filter($arr, function($v) use ($target, $epsilon) {
return abs($v - $target) < $epsilon;
});
null/false 的情况array_filter() 默认会过滤掉 false、0、""、null 等“falsy”值,这在浮点筛选中极易误伤 —— 比如 0.0 是合法浮点数,但会被默认行为剔除。
ARRAY_FILTER_USE_BOTH 或使用回调函数,并确保返回布尔值而非原始值array_filter($arr, 'abs') ——abs(0.0) 返回 0,被当作 false 过滤掉"0.3"),先用 is_numeric() 或 filter_var($v, FILTER_VALIDATE_FLOAT) 预检,否则 abs($v - $target) 可能触发警告或返回意外结果$result = array_filter($arr, function($v) use ($target, $epsilon) {
if (!is_numeric($v)) return false;
return abs((float)$v - $target) < $epsilon;
});
重复写 abs($v - $target) 易出错且难维护。封装时注意两点:不隐藏容差逻辑,不牺牲调试便利性。
float_in_range(),而非模糊的 is_equal()
$epsilon 设为可选参数,默认值设为 1e-8,但文档/注释里强调“请按需调整”(float)),让调用方决定如何清洗输入function float_array_filter(array $arr, float $target, float $epsilon = 1e-8): array
{
return array_filter($arr, function($v) use ($target, $epsilon) {
return is_numeric($v) && abs($v - $target) < $epsilon;
});
}
真正容易被忽略的是:当数组元素本身来自不同计算路径(比如有的来自 bcadd(),有的来自普通运算),它们的误差分布并不均匀。这时候单一 $epsilon 可能不够 —— 你需要先用 var_dump(array_map('sprintf', $arr, array_fill(0, count($arr), '%.17g'))) 看清实际存储值,再决定容差策略。