php中int与float是底层完全独立的类型,存储、比较、数组键匹配、json处理等行为均不同,布尔值也是独立类型,易因隐式转换出错;安全类型判断需用filter_var等函数而非is_int。

整数和浮点数在 PHP 里不是“能算就行”,而是存储和比较逻辑完全不同
PHP 的 int 和 float 在底层是两种独立类型,即使你写 5 和 5.0,它们的类型、内存布局、哈希值、甚至数组键匹配行为都可能不一致。这不是 PHP “松散”带来的错觉,而是真实差异。
常见错误现象:
– array_key_exists(5.0, [5 => 'ok']) 返回 false(因为键是 float,而数组里存的是 int)
– var_dump(0 == 0.0) 输出 bool(true),但 var_dump(0 === 0.0) 是 bool(false)
– json_encode([5 => 'a', 5.0 => 'b']) 只保留一个键(JSON 键强制转为字符串,"5" 冲突)
- 整数用补码二进制直接存数值,精确、无舍入;浮点数走 IEEE 754(PHP 默认双精度),
0.1 + 0.2 !== 0.3是必然结果,不是 bug - PHP 不会自动把
float转成int去当数组键用——除非你显式调用(int)或intval(),否则类型就卡死在那里 - 性能上,整数运算快、可被 OPcache 更好优化;浮点数涉及指数对齐、尾数归一化,还可能触发 FPU 指令路径,尤其在循环中累积误差+性能损耗更明显
布尔值在 PHP 里根本不是“真假数字”,它是个独立的 type,但又最容易被隐式转换坑
PHP 的 bool 类型只有两个值:true 和 false,它既不是整数 1/0,也不是字符串 "1"/"",但在松散比较(==)时会被强制转成其他类型——这正是大多数混淆的源头。
常见错误现象:
– if ([] == false) 成立(空数组被当成 false)
– var_dump((bool)"0") 是 bool(false)(字符串 "0" 是唯一被判定为 false 的非空字符串)
– json_encode([true => 'yes', false => 'no']) 得到 {"1":"yes","":"no"}(key 被转成字符串)
立即学习“PHP免费学习笔记(深入)”;
- 判断真假请用严格比较:
=== true或=== false;避免用== 1或== 0判布尔 - 函数返回布尔值时,别直接拿去算术运算:
$count += $found看似省事,但$found是true时加的是 1,是false时加的是 0 —— 这依赖隐式转换,可读性差且易出错 - 数据库字段映射要注意:MySQL 的 TINYINT(1) 常被 PDO 当作
int返回,不是bool;想得到布尔得手动配置PDO::ATTR_EMULATE_PREPARES => false并启用PDO::MYSQL_ATTR_DIRECT_QUERY,或自己 cast
怎么安全地做类型判断和转换?别信 is_int($x) 就万事大吉
is_int() 只检查运行时类型,不关心值是否“看起来像整数”。比如 is_int("123") 是 false,但 is_int(123.0) 也是 false——因为 123.0 是 float,哪怕它数学上等于整数。
使用场景:
– 接口参数校验要区分“必须是整数”还是“可以是数字字符串”
– JSON 解析后所有数字默认是 float,哪怕原始是 123(PHP 8.2+ 有 JSON_INVALID_UTF8_IGNORE 但没数字类型保留选项)
- 判断“是否可无损转为整数”:用
filter_var($x, FILTER_VALIDATE_INT) !== false,它能处理字符串"123"、"-456",但拒绝"12.3"、"abc" - 强制转整数优先用
(int),但注意截断不四舍五入;需要四舍五入请用round($x, 0, PHP_ROUND_HALF_DOWN) - 从 float 安全转 int:先用
is_finite($x)排除 INF/NAN,再用floor($x) === $x判断是否为整数值,最后(int)$x转换
PHP 8.0+ 的联合类型和属性类型声明,让区别不再“靠猜”
过去靠文档或注释说明“这个参数应该是 int”,现在可以直接写 function foo(int|float $x): void。但这不是万能胶——联合类型只约束输入输出,不改变底层行为。
容易踩的坑:
– function bar(int $x): void { echo $x + 0.5; } 传入 3 没问题,但返回值仍是 float,类型声明不覆盖运行时计算逻辑
– 属性声明 public int $count = 0; 在构造后仍可能被外部赋值为 float,除非配合 __set() 拦截或启用严格模式
- 开启
declare(strict_types=1);是前提,否则类型声明只在调用处校验,不阻止内部 float 混入 - 数组元素类型无法用联合类型直接约束(
array<int></int>是无效语法),得用array+ PHPDoc 或 PHPStan/psalm 静态分析补位 - JSON 解析仍是最大漏网之鱼:无论你怎么声明
array{score: int},json_decode($json, true)返回的score字段永远是 float —— 因为 JSON 规范没有整数/浮点数区分
json_encode() 和 array_key_exists() 对同一个数值给出不同答案。











