为什么会存在浮点数计算精度丢失问题,这个原因不再过多赘述; JS中如何解决精度计算问题,大不部分人都知道升幂再降幂的解决方案; 但是如果直接升幂也会出现精度问题,且需要指定死小数位数。如:
var m = 100; //0.28 * 100 升幂时就会出现精度问题 var res = ((0.28 * m) + (0.03*m)) / m ; // 0.31000000000000005 //需要再对结果进行一次Math.toFixed处理,且需要指定小数位数 res.Math.toFixed(2) //0.31
本文为大家重新整理了一个_Calc JS高精度计算方法,并放在了博主的开源库Jsutil中; *采用的是replace+数字补0 实现升幂; 方法测试结果,以excel计算做为参照: 1、支持加,减,乘,除 2、支持连续数字计算; 方法源码:
const _Calc = (symbol:string, number1:number, number2:number, ...args:number[]):number =>{ if(!['+','-','*','/'].includes(symbol)){ throw new Error('第一个参数请传+ - * /计算符'); } const num1 = Number(number1); const num2 = Number(number2); if(isNaN(num1) || isNaN(num2)){ throw new Error('第二,三个参数必须传入可计算数字或字符'); } let result = 0; // 把浮点数跟整数部分拆解 const [num1BeforeInt, num1Float] = num1.toString().split('.'); const [num2BeforeInt, num2Float] = num2.toString().split('.'); const num1FloatLen = num1Float?.length || 0; const num2FloatLen = num2Float?.length || 0; // 乘除法直接去掉浮点 const num1Int = Number(num1.toString().replace('.','')); const num2Int = Number(num2.toString().replace('.','')); if(symbol === '+' || symbol === '-'){ // 以最长浮点数长度补0 let m = Math.max(num1FloatLen, num2FloatLen); // 使用字符串补0方式得到最后计算数值(不能直接数字升幂,部分数字升幂就会缺精度) const resNum1 = Number(`${num1BeforeInt}${num1Float.padEnd(m,'0')}`); const resNum2 = Number(`${num2BeforeInt}${num2Float.padEnd(m,'0')}`); if(symbol === '+'){ result = (resNum1 + resNum2) / Math.pow(10, m); }else{ result = (resNum1 - resNum2) / Math.pow(10, m); } }else if(symbol === '*'){ // 两个数的浮点长度加和为幂值 let m = Math.pow(10, num1FloatLen + num2FloatLen); result = (num1Int * num2Int ) / m; }else if(symbol === '/'){ // 被除数的浮点长度减除数浮点长为幂值 let m = Math.pow(10, num2FloatLen - num1FloatLen) result = (num1Int / num2Int ) * m; } // 有第三位计算数字 const nextNum = args[0]; if(nextNum){ args.shift() result = _Calc(symbol, result, nextNum, ...args); } return result; }
标签:const,Jsutil,symbol,Number,js,源码,result,Math,升幂 From: https://www.cnblogs.com/hrw3c/p/16710644.html