PHP用浮点数作数组键会静默截断为整数:3.9→3、0.30000000000000004→0、-2.8→-2;var_dump可能显示浮点字面量但实际键为整型;需用sprintf('%.15g', $float)转字符串键保留精度。

PHP 数组用浮点数当键会怎样
PHP 允许用浮点数作为数组下标,但实际不会保留小数部分——它会自动强制转换为整数。这不是报错或警告,而是静默截断,容易引发逻辑错误。
-
floatval(3.9)作键 → 实际存成3 -
0.1 + 0.2得到的0.30000000000000004作键 → 强制转成0 - 负浮点数如
-2.8→ 转成-2(向零截断,不是四舍五入)
为什么 var_dump() 看起来“支持”浮点键
当你写 $arr[3.7] = 'x'; 再 var_dump($arr),输出可能显示 [3] => 'x',但有些版本或扩展(如 Xdebug)会在键名上显示原始浮点字面量,造成“还活着”的错觉。本质仍是 int 键,只是调试器渲染方式不同。
- 真实键类型可用
gettype(key($arr))验证,结果是integer -
array_keys($arr)返回的全是整数,没有浮点 - 用
foreach ($arr as $k => $v)遍历时,$k永远是 int
想存浮点精度的“键”,该怎么做
必须放弃原生数组下标语义,改用字符串键来保留精度。这是唯一可靠方式,尤其涉及金额、坐标、科学计算等场景。
- 用
sprintf('%.15g', $float)格式化,避免科学计数法和尾部 0(如0.1不变,1.0不变,1e-5变成0.00001) - 避免直接
(string)$float:PHP 浮点转字符串受serialize_precision影响,可能丢精度 - 示例:
$data[sprintf('%.15g', 0.1 + 0.2)] = 'result';→ 键为'0.30000000000000004',可准确匹配
isset() 和 array_key_exists() 对浮点键的判断差异
两者都按转换后的整数去查,但行为一致:传入浮点参数时,先转 int,再查是否存在。所以 isset($arr[3.9]) 等价于 isset($arr[3])。
立即学习“PHP免费学习笔记(深入)”;
- 如果
$arr[3]存在,isset($arr[3.9])返回true,哪怕你从没显式赋过3.9键 - 同理,
array_key_exists(3.9, $arr)也查的是3 - 这会让条件判断产生歧义,尤其是键本意是区分不同浮点值时
sprintf 调用。











