You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel调用第三方API数据精度异常问题求助

Laravel调用第三方API浮点数精度丢失问题解决

问题现象

  • 调用第三方API后,Chrome预览面板显示buyAmount为7.31这类正常十进制数值
  • 但Laravel解析响应后、存入MySQL的JSON数据中,buyAmount变为7.3099999999999996这类精度异常值
  • 尝试用round()、abs()处理无效,Postman测试或print_r()输出数据却显示正常

原因分析

  1. 二进制浮点数存储局限:7.31这类十进制小数无法用二进制浮点数(PHP的float为双精度类型)精确表示,解析后会自动转为近似的二进制浮点值
  2. 渲染/输出差异:Chrome、Postman直接显示API返回的原始JSON字符串,未做浮点转换;print_r()会对浮点数做近似格式化显示,但内存中实际存储的仍是精度丢失的数值
  3. round()失效原因:浮点数本身的精度问题导致round()处理后,内存中的值仍为近似值,json_encode时会输出原始精度的数值,而非期望的格式化结果

解决方案

方案1:高精度字符串处理(推荐)

使用PHP的bcmath扩展(需开启)直接处理字符串类型的数值,避免浮点转换:

$url = $this->config['baseUrl'];
$response = Http::get($url);

// 解析JSON时强制将数值转为字符串,保留原始精度
$res = json_decode($response->body(), true, 512, JSON_BIGINT_AS_STRING);

// 用bcadd做高精度小数格式化,保留6位小数
$processed = [
    "buyAmount" => bcadd($res["buyAmount"], 0, 6),
    "clientRate" => bcadd($res["clientRate"], 0, 6),
    "marketRate" => bcadd($res["marketRate"], 0, 6),
];

// 编码时保留小数格式
$encoded = json_encode($processed, JSON_PRESERVE_ZERO_FRACTION);
$quote = DBModel::create(["response" => $encoded]);

方案2:强制格式化数值后编码

先将数值格式化为指定小数位数的字符串,再转回浮点数,确保json_encode输出正确格式:

$url = $this->config['baseUrl'];
$response = Http::get($url);
$res = $response->json();

// 用number_format强制保留6位小数,再转回浮点数
$processed = [
    "buyAmount" => (float)number_format((float)$res["buyAmount"], 6, '.', ''),
    "clientRate" => (float)number_format((float)$res["clientRate"], 6, '.', ''),
    "marketRate" => (float)number_format((float)$res["marketRate"], 6, '.', ''),
];

// 编码时启用小数保留参数
$encoded = json_encode($processed, JSON_PRESERVE_ZERO_FRACTION);
$quote = DBModel::create(["response" => $encoded]);

方案3:直接存储字符串类型数值

如果不需要在数据库中对数值做计算,可直接保留原始字符串类型,完全避免浮点转换:

$url = $this->config['baseUrl'];
$response = Http::get($url);

// 解析时保留数值为字符串
$res = json_decode($response->body(), true, 512, JSON_BIGINT_AS_STRING);

// 直接编码字符串数值
$encoded = json_encode([
    "buyAmount" => $res["buyAmount"],
    "clientRate" => $res["clientRate"],
    "marketRate" => $res["marketRate"],
]);
$quote = DBModel::create(["response" => $encoded]);

内容的提问来源于stack exchange,提问作者Imtehariya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 14:07:43