php 8.1 并未引入 decimal 类型,小数仍用 float 表示,存在精度问题;应使用字符串(如 "8.10")配合 bcmath、转为整数单位(如“分”)或第三方库(如 brick/math)来确保精确计算。

PHP 8.1 的 decimal 类型并不存在
PHP 8.1 没有引入 decimal 类型,也没有 _decimal 返回类型。这是常见误解——可能混淆了其他语言(如 Python 的 decimal 模块)或误读了 RFC 提案。PHP 官方至今未添加原生十进制浮点类型,所有小数仍由 float 表示,底层依赖 IEEE 754 双精度,这意味着 0.1 + 0.2 !== 0.3 是常态。
保存小数 8.1 的实际做法:别信 float 直存
直接赋值 $x = 8.1; 看似无害,但 var_dump($x) 可能显示 float(8.0999999999999996) —— 这是二进制浮点固有精度缺陷。金融、计费等场景必须规避:
- 用字符串存储:如
$amount = "8.10";,后续交由bcadd()、bcmul()等 BCMath 函数运算 - 转为整数单位:如以“分”为单位存
$cents = 810;,彻底避开小数 - 使用第三方库(如
brick/math),它提供不可变的BigDecimal对象,支持精确十进制算术
PHP 8.1 真正相关的新特性:ReturnTypeWillChange 和枚举
与小数精度无关,但常被误关联:
-
ReturnTypeWillChange是一个属性,用于标记实现Iterator接口的方法(如current()、key())将忽略返回类型声明检查,方便升级到 PHP 8+ 的严格模式 - 枚举(
enum)在 8.1 引入,可用于定义固定状态(如enum OrderStatus: string { case PAID = "paid"; }),但不解决数值精度问题 - 没有新增任何数学类型或内置高精度数值类
为什么有人坚持要“decimal”?现实痛点在哪
核心矛盾在于:PHP 的 float 不适合表示十进制小数,而开发者又习惯写 8.1 这样的字面量。容易踩的坑包括:
立即学习“PHP免费学习笔记(深入)”;
- 数据库写入时,
float被截断或四舍五入(尤其 MySQL 的FLOATvsDECIMAL(10,2)类型不匹配) - JSON 编码后丢失精度:
json_encode(['price' => 8.1])可能输出{"price":8.0999999999999996} - 类型声明误导:
function calc(float $x): float无法保证输入/输出是“人类理解的十进制小数”
真正稳的方案不是等 PHP 加 decimal,而是从第一行代码就放弃对 float 的信任,用字符串或整数建模业务中的“钱”“重量”“百分比”。这比纠结语法糖更关键。











