做项目的时候,涉及到商品价格的计算,经常会出现计算出现精度问题。刚开始草草了事,直接用toFixed就解决了问题,并没有好好的思考一下这个问题。后来慢慢的,问题越来越多,连toFixed也出现了(允悲),后来经过搜索网上的各种博客和论坛,整理总结了一下。
浮点数运算后的精度问题
在计算商品价格加减乘除时,偶尔会出现精度问题,一些常见的例子如下:
// 加法 =====================
0.1 + 0.2 = 0.30000000000000004
0.7 + 0.1 = 0.7999999999999999
0.2 + 0.4 = 0.6000000000000001
// 减法 =====================
1.5 - 1.2 = 0.30000000000000004
0.3 - 0.2 = 0.09999999999999998
// 乘法 =====================
19.9 * 100 = 1989.9999999999998
0.8 * 3 = 2.4000000000000004
35.41 * 100 = 3540.9999999999995
// 除法 =====================
0.3 / 0.1 = 2.9999999999999996
0.69 / 10 = 0.06899999999999999
toFixed奇葩问题
在遇到浮点数运算后出现的精度问题时,刚开始我是使用toFixed(2)来解决的,因为在W3school和菜鸟教程(他们均表示这锅不背)上明确写着定义:toFixed()方法可把Number四舍五入为指定小数位数的数字。
解决方法
针对以上问题,网上搜了一波解决方法,来看一下。
加法
// 加法
export function accAdd(arg1 = '', arg2 = '') {
var r1, r2, m
try { r1 = (arg1).toString().split('.')[1].length } catch (e) { r1 = 0 }
try { r2 = (arg2).toString().split('.')[1].length } catch (e) { r2 = 0 }
m = Math.pow(10, Math.max(r1, r2))
return (arg1 * m + arg2 * m) / m
}
减法
// 减法
export function Subtr(arg1 = '', arg2 = '') {
var r1, r2, m, n
try { r1 = (arg1).toString().split('.')[1].length } catch (e) { r1 = 0 }
try { r2 = (arg2).toString().split('.')[1].length } catch (e) { r2 = 0 }
m = Math.pow(10, Math.max(r1, r2))
n = (r1 >= r2) ? r1 : r2
return ((arg1 * m - arg2 * m) / m).toFixed(n)
}
乘法
// 乘法
export function accMul(arg1 = '', arg2 = '') {
var m = 0; var s1 = (arg1).toString(); var s2 = (arg2).toString()
try { m += s1.split('.')[1].length } catch (e) { }
try { m += s2.split('.')[1].length } catch (e) { }
return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m)
}
除法
// 除法
export function accDiv(arg1 = '', arg2 = '') {
var t1 = 0; var t2 = 0; var r1; var r2
try { t1 = (arg1).toString().split('.')[1].length } catch (e) { }
try { t2 = (arg2).toString().split('.')[1].length } catch (e) { }
// with (Math) {
r1 = Number((arg1).toString().replace('.', ''))
r2 = Number((arg2).toString().replace('.', ''))
return accMul((r1 / r2), Math.pow(10, t2 - t1))
// }
}
总结
经过测试,可解决计算精度问题,如有不对的地方,欢迎指出。
网友评论