今天用vue做小数点转换百分比的时候遇到:36*19.2 = 691.1999999999999 ,起初以为是vue计算方式有问题,后来想到js有小数点失精的问题,结果测试了一下果然是这个问题:
js失精算法
console.log(0.1+0.2); // 0.30000000000000004
console.log(0.07*100); // 7.000000000000001
console.log(0.119*100); // 11.899999999999999
…
结果为什么会这样?
解决的思路有:
1.parseInt,parseFloat
大多数情况下不需要小数点后很多位,可以使用toFixed(n)方法修正后(n是小数后精确的位数)。
console.log(36*19.2); // 691.1999999999999
parseFloat((36*19.2).toFixed(10)); // 691.2
2.计算出小数点后位数的大的一个,乘法消去小数点做整数运算后做除法
Math.round(arg1 * m - arg2 * m) / m
Math.round(( 36*19.2)*1000)/1000; // 691.2
还可以用 位运算符、转化为字符串处理(Number(s1.replace(“.”, “”)) * Number(s2.replace(“.”, “”)) / Math.pow(10, m))、第三方插件库(big.js,bignumber.js,decimal.js等等)等方式进行处理。
既然找到解决方式,在Vue中使用就可
<td>{{data | getPercentage}}%</td>
Vue.filter("getPercentage", function(value) { //全局方法 Vue.filter() 注册一个自定义过滤器,必须放在Vue实例化前面 return
Math.round((value * 100)*1000)/1000;
});
computed:{
getPercentage:function () {
return data* 100
}}
js计算避免加减出现误差
//消除js计算误差add、reduce是传入的加减数字,reduce是被加数(被减数),s是加减符号
function formatNum(add: number, reduce: number, s: string, num: number) {
let m = Math.pow(10, num); //num是10的次幂
let res = s == '+' ? (add * m + reduce * m) / m : (add * m - reduce * m) / m;
return Math.round(res * m)/m;
}