后端保留两位小数,前端显示却丢失了,查了下,是 js 解析 float 精度丢失。不想在后端改成 string,怎么让前端正确显示。
后端 php 是 float 保留两位小数,转为 json。
["money"]=> array(3) { ["maket_total"]=> float(16794.48) ["voucher_total"]=> string(6) "744.00" ["favorable_total"]=> float(509.46) }
前端接收却是:"money":{"maket_total":16794.48,"voucher_total":"744.00","favorable_total":509.46000000000004}},
array(4) { ["data"]=> array(2) { ["saled"]=> object(Illuminate\Database\Eloquent\Collection)#1235 (1) { ["items":protected]=> array(0) { } } ["money"]=> array(3) { ["maket_total"]=> float(16794.48) ["voucher_total"]=> string(6) "744.00" ["favorable_total"]=> float(509.46) } } ["status"]=> int(0) ["msg"]=> string(12) "操作成功" ["total"]=> int(0) } php的json_encode()之后: string(170) "{"data":{"saled":[],"money":{"maket_total":16794.48,"voucher_total":"744.00","favorable_total":509.46000000000004}},"status":0,"msg":"\u64cd\u4f5c\u6210\u529f","total":0}"
然后json_encode()就丢失精度了
1 TommyLemon 2018-10-31 17:28:30 +08:00 ![]() 也保留两位小数 |
2 TomatoYuyuko 2018-10-31 17:30:28 +08:00 ![]() 不了解 php 怎么做的,我这里大概思路是用 string 类型传送浮点数,然后前端再做处理。 |
![]() | 3 mentalidade OP |
![]() | 4 HanMeiM 2018-10-31 17:42:58 +08:00 ![]() 一般要么存整数,要么传 string |
![]() | 5 |
![]() | 6 mentalidade OP |
7 micean 2018-10-31 17:54:21 +08:00 ![]() 钱的话谨慎用 toFixed |
![]() | 8 HanMeiM 2018-10-31 17:55:20 +08:00 ![]() @mentalidade 是后端啊,这里没说是钱啊。其次我们的钱单位为厘,分的更小一位 |
![]() | 9 SakuraKuma 2018-10-31 18:00:17 +08:00 ![]() 钱的话建议传 /存储都是整数不要小数。 小数只是显示用。 这浮点数精度无解的 |
![]() | 10 MrJeff 2018-10-31 18:00:58 +08:00 ![]() 用 string 吧 省事 |
![]() | 11 westoy 2018-10-31 18:01:44 +08:00 小额可以传 long, 末两位做小数, 注意控制溢出 或者传字符窜, 用 decimal 或者 gmp 既然不想在后端改, 那就无解了 浮点一时爽, 会计对账小一半订单有个几毛几分的误差就 happy 了 |
12 TomatoYuyuko 2018-10-31 18:08:27 +08:00 ![]() @mentalidade 前端,一般来说前端不处理数据,只负责呈现,没有特别需求保留 2 位小数就好了。 当然数据库你肯定要存精确的,你可以直接在服务端把数字精确处理后再给前端。或者 string 之后给前端处理。 js 这类语言对浮点数处理会有误差,尽可能不要让 js 处理小数运算。 |
13 atcdef 2018-10-31 19:28:29 +08:00 ![]() 这个无解的,要么前端格式化一下再显示,要么后端传格式化好的字符串来。我一般都是传格式化好的字符串到前端 |
![]() | 14 8e47e42 2018-10-31 19:37:46 +08:00 ![]() 一般比较容易的是直接传 string,当然也可以选择成本扩大变成 bigint,当然很多库默认都不支持 bigint,然后你懂的,GG,到最后还是变成了传 string 最靠谱。 |
15 sxlzll 2018-10-31 22:15:12 +08:00 如果是钱,单位可以改成分 其他的 float,确实比较稳妥的做法是两个字段,data, data_str |
![]() | 16 dd112389 2018-11-01 01:00:47 +08:00 ![]() 这里有个坑,前些天才遇到过. 你可以看一下 php 的 json_encode 函数的说明, 里面有写 php.ini 中的一个设置 serialize_precision 会导致 json_encode 的精度丢失问题. 将这个设置改为 16 以下应该就不会了. ini_set('serialize_precision', 15); |
17 justyue 2018-11-01 08:37:13 +08:00 via iPhone ![]() 我司,钱都是转成 string 传的,安全方便 |
![]() | 18 mentalidade OP @dd112389 #16 是的,我发现是 json_encode()的问题,但是上面的实际的例子,maket_total 这个值就没事,favorable_total 却发生了精度丢失,明明两个都是保留两位小数的 float ?求解 |
![]() | 19 weixiangzhe 2018-11-01 09:24:56 +08:00 我司都是整数 |
![]() | 20 lukunlin 2018-11-01 09:51:36 +08:00 .toFixed(2)一下就好了啊~ |
![]() | 21 BBCCBB 2018-11-01 10:18:32 +08:00 long 类型 超过 53 还是 54, js 解析也会出问题的, 还是用 string 吧. |
![]() | 22 BBCCBB 2018-11-01 10:18:55 +08:00 53, 54 位 |
23 promise2mm 2018-11-01 11:13:33 +08:00 http://www.css88.com/archives/7340#more-7340 这里有大佬的分析,我司也遇到过 |
![]() | 24 shuang 2018-11-01 11:27:31 +08:00 0.495.toFixed(2) "0.49" |
![]() | 25 kran 2018-11-01 11:29:56 +08:00 via iPhone 乘上 10^n 再编码成 json |
![]() | 26 zjsxwc 2018-11-01 11:32:00 +08:00 php7.1.x 特定小版本的问题, 加一句 ``` ini_set('serialize_precision', -1); ``` 就行 http://php-symfony.uk/json_encode-producing-unexpected-float-values-in-php-7-1/ |
![]() | 27 msg7086 2018-11-01 11:37:06 +08:00 钱用浮点数这种近似表示法是作大死。只要是近似表示,就会有误差,再怎么都会有。 |
28 Jobing 2022-11-05 21:36:44 +08:00 可以用这个开源库解决: https://github.com/jobinben/json-bn |