数据库约束了数据为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
 
                

 微信扫一扫
                                                            微信扫一扫                                                     支付宝扫一扫
                                                            支付宝扫一扫                                                     
            