数据库约束了数据为decimal(10,2),根据thinkphp的特性,读取数据库是都会转为字符串,但奇怪的地方是,整个计算过程都毫无异常,组合成新数组时,出现了错误,错误如下:
整个数据的精度发生了变化,其实原因不难分析,无非就是计算机对浮点数精度无法把握而已,那么,到底是哪个环节让精度发生了变化呢?
约束新数组
从上面的情况可知,错误是在组合新数组时发生了错误,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 处理抓取的信息 $num = 0; foreach($list as $k=>$info){ $receivable_money = 0; $received_money = 0; if(!empty($info)){ $keys = $num++; foreach($info as $i){ if($i['financial_item']==$k){ $receivable_money += $i['financial_money_receivable']; $received_money += $i['financial_money_received']; $data[$keys]['item_name'] = $k; $data[$keys]['receivable_money'] = $receivable_money; $data[$keys]['received_money'] = $received_money; $data[$keys]['financial_data'] = $i['financial_data']; } } } } |
所以我尝试在组成新数组前,对数据进行二次约束,新的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 处理抓取的信息 $num = 0; foreach($list as $k=>$info){ $receivable_money = 0; $received_money = 0; if(!empty($info)){ $keys = $num++; foreach($info as $i){ if($i['financial_item']==$k){ $receivable_money += $i['financial_money_receivable']; $received_money += $i['financial_money_received']; $data[$keys]['item_name'] = $k; $data[$keys]['receivable_money'] = number_format($receivable_money,2); $data[$keys]['received_money'] = number_format($received_money,2); $data[$keys]['financial_data'] = $i['financial_data']; } } } } |
如上处理后,前端得到了正确精度的数据,诧异的是,此刻前端却出了新问题。
无法计算
按上面的方式处理后,前端的计算结果变成了NaN,如下图:
前端的计算公式是:
1 2 |
var rate = ((c.received_money/c.receivable_money)*100).toFixed(2); console.log(c.received_money/c.receivable_money); |
无论打印c.received_money还是c.receivable_money,均输出正确的结果,偏偏进行相除,变成了NaN。
这时候就需要确认一下,我们前端得到的这个浮点数,数据类型是什么。
1 |
console.log(typeof(c.received_money)); |
打印数据类型发现,我们得到的数据类型是string,所以,问题出在这里,要解决这个问题,只需要将数据转为浮点数即可。
js提供了parseInt()和parseFloat()两个转换函数。前者把值转换成整数,后者把值转换成浮点数。
1 |
console.log(typeof(parseFloat(c.received_money))); |
再次打印,可以看到数据类型变为了number。
真实原因
排查半天后发现,原因在一开始,错误的使用
1 |
number_format($receivable_money,2) |
这是千分位形式的数字呈现方式,默认就是字符串,转为数字,结果会完全错误,结果自然也就错误。
因为是浮点数,在进行储存,转换的过程中,势必会有精度的问题。
解决的办法是,在计算完成后,约束结果为字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// 处理抓取的信息 $num = 0; foreach($list as $k=>$info){ $receivable_money = 0; $received_money = 0; if(!empty($info)){ $keys = $num++; foreach($info as $i){ if($i['financial_item']==$k){ $receivable_money += $i['financial_money_receivable']; $received_money += $i['financial_money_received']; settype($receivable_money,"string"); settype($received_money,"string" ); $data[$keys]['item_name'] = $k; $data[$keys]['receivable_money'] = $receivable_money; $data[$keys]['received_money'] = $received_money; $data[$keys]['financial_data'] = $i['financial_data']; } } } } |
这两句代码起到关键作用:
1 2 |
settype($receivable_money,"string"); settype($received_money,"string" ); |
原创文章,作者:蓝洛水深,如若转载,请注明出处:https://blog.lanluo.cn/10652