在开发中经常遇见浮点数计算,但因为计算机在计算浮点数时都会因为精度问题造成计算的数值出现误差(精度丢失并不是js语言独有的,只有是采用IEEE 754 标准来表示浮点数的语言都会出现精度误差),所以今天写了一个计算工具函数来处理下
因精度丢失而产生的问题,如图所示
工具函数,支持加减乘除
/**
* 浮点数计算
* 支持 +-/*
* 支持多位计算
* @argument args 浮点数组
* @argument operator 操作符,默认+
*
*/
function computeFloatNumber(args,operator='+') {
if(arguments.length===0) return
if(!Array.isArray(args)) {
throw new Error('The argument should be an array!')
}
if(args.length<=1) return args[0]
// 获取浮点数组里最大的精度
const precision = Math.max(...args.map(d=>getDecimalLength(d)));
// 数字的幂的内置函数 Math.pow(10, 2)=> 100
const multiplier = Math.pow(10, precision);
// 浮点数组转为整数数组
const nums = args.map(d=>Math.round(d*multiplier))
let result=0
switch (operator) {
// 使用reduce可以实现多位累计计算
case '+':
result = nums.reduce((p,n)=>p+n);
break
case '-':
result = nums.reduce((p,n)=>p-n);
break
case '*':
result = nums.reduce((p,n)=>p*n);
break
case '/':
result = nums.reduce((p,n)=>p/n);
break
default:
return 'Invalid operator';
}
if(operator==='/') return result
if(operator==='*') {
let _mul = Math.pow(10, precision*nums.length);
console.log('_mul',nums,_mul,result)
return result/_mul
}
return result/multiplier
}
// 获取浮点数精度位数
function getDecimalLength(num) {
const [, decimal] = String(num).split('.');
return decimal ? decimal.length : 0;
}
ps:
- 整数之间计算是不会产生精度问题的,在遇见浮点计算时,最好是将浮点数转为整数