PHP给JSON对象添加float值后编码出现小数精度异常问题
PHP json_encode编码float类型出现长小数问题解决
问题现象
使用PHP开发时,将float类型数值0.3赋值给stdClass实例的属性后调用json_encode编码,编码结果中原float值变成了长小数,测试复现代码如下:
<?php $test = 0.3; $data = new stdClass(); $data->test = $test; echo json_encode ($data); // 默认配置下输出结果类似:{"test":0.30000000000000004} ?>
问题原因
- 二进制浮点数的固有特性:0.3这类十进制小数无法用二进制浮点数精确存储,实际存储的是接近0.3的近似值。日常输出时PHP默认会截断显示为0.3,但
json_encode默认会输出浮点数的完整存储精度,因此会出现长小数。 - PHP配置原因:PHP 7.1及以上版本中
json_encode默认使用serialize_precision配置项控制浮点数序列化精度,部分环境该配置默认值为100,会输出完整的近似值内容。
解决方案
方案1:调整serialize_precision全局配置
在代码入口或者执行json_encode前添加配置,设置合理的序列化精度即可:
// 设置为-1时PHP会自动选择最合适的短精度表示,兼容PHP 7.1+ ini_set('serialize_precision', -1); // 也可设置为固定精度如14,满足绝大多数场景的精度需求 // ini_set('serialize_precision', 14); $test = 0.3; $data = new stdClass(); $data->test = $test; echo json_encode($data); // 输出:{"test":0.3}
方案2:局部处理浮点数精度
如果不想修改全局配置影响其他业务逻辑,可以单独对需要编码的浮点数做精度格式化:
$test = 0.3; // 先格式化为指定小数位后再转回float类型 $test = (float)sprintf("%.1f", $test); $data = new stdClass(); $data->test = $test; echo json_encode($data);
方案3:高敏感场景规避float类型
如果是金额、精准计量等对精度要求极高的业务场景,不要使用float类型存储数值:
- 用整数存储最小单位,比如金额存储为分单位的整数
- 用字符串格式存储数值,配合BCMath系列函数做运算,编码时可根据需要转成数值或保留字符串格式
内容的提问来源于stack exchange,提问作者Motorhomer
相关产品推荐
相关产品推荐

