背景
背景是这样子的,首先有个一个表格,表格底部有一个统计金额的需求,而且表格的数据是可以搜索过滤的,所以统计金额的任务就交给前端来做啦。前端做的话也简单,用 Array.prototype.reduce
方法就可以搞定:
1 | const sum = data.reduce((prev, curr) => { |
两行代码就搞定了,自测了一下,没什么问题,提交测试。
问题
但是,万万没想到啊,测试竟然给我提BUG了,大概意思就是在几千条数据的时候,统计的金额数据与数据库的统计数据差了几分钱。我脑中第一个想法就是 JavaScript 的小数精度问题,但是仔细想了一下,小数的精度问题只有在小数十多位后才会存在,所以这个想法瞬间就被否决了。于是,我陷入了沉思。。。
思索了半天还是没有头绪,于是就 Google 了下小数精度的问题,找到了这篇文章,看到 0.1+0.2=0.30000000000000004
这里,我就瞬间明白了,JavaScript 的小数精度问题并不是在小数点后面十几位才有,一两位也有啊。所以,刚刚的问题就找到了。由于金额在数据库中是只保留2位小数,在数据量少的时候,JavaScript 的精度问题不至于影响最终的统计数据,但是在数据量大的时候,已经可以影响到数据的显示,也就是之前说的,差了几分钱的问题。
解决
知道发生问题的原因,解决起来就好办了。由于我们的需求是金额保留2位小数,而且精度问题只会在数据量大的时候才会出现。所以,我的解决办法就是,每次遍历相加的时候,就去做一次精度处理,也就是每次相加后,保留2位小数,以防多次相加后,小数精度问题被放大。贴上修改后的代码:
1 | const sum = data.reduce((prev, curr) => { |
总结
其实,JavaScript 存在小数精度问题我之前是了解的,但是了解的不是很全面,或者是之前没踩到这个坑,才会出现这个问题。究其根本,还是对 JavaScript 基础掌握得不够,在这方面,以后得多多加强。