前端开发者都了解js计算问题,可以通过一些库解决。由于不太会找库,所以自己写了一个。
class HighPrecisionCalc {
constructor() {
}
// 判断是否是整数,严谨性判断(是字符串也不行)
isInteger(val) {
return Math.floor(val) === val
}
// 得到整数
toInteger(floatNum) {
// 如果是字符串先转换成数字
floatNum = +floatNum
if (isNaN(floatNum)) {
throw TypeError('you passed params must be can transform Number type,but not can be NAN')
return
}
//默认整数的对象
let ret = {
originNum: floatNum,//原数值(数字类型)
IntNum: floatNum, //去掉小数点的数
//小数的长度
len: 0
}
// 如果是整数接直接返回上面的对象
if (this.isInteger(floatNum)) {
return ret
} else {
//如果是小数
// 转成字符串
let stringNum = floatNum + '';
//得到小数点后面的长度
let dotPos = stringNum.indexOf('.');
let len = stringNum.substr(dotPos + 1).length;
// 得到整数(替换小数点)
ret.IntNum = +(stringNum.replace('.', ''))
// 长度值
ret.len = len
// 返回这个对象
return ret
}
}
//toInteger得到的整数是不在乎倍数的。在这里要处理为统一的倍数
handleCommonTimes(n1, n2) {
//小数点后面最大长度
let maxLen = n1.len > n2.len ? n1.len : n2.len;
//得到整数
let num1 = n1.IntNum;
let num2 = n2.IntNum;
//整数公共倍数结果(公积数,都是乘以相同的倍数)
num1 = num1 * (Math.pow(10, maxLen - n1.len));
num2 = num2 * (Math.pow(10, maxLen - n2.len));
//返回
return {
IntNum1: num1, IntNum2: num2, maxLen
}
}
//操作
operation(num1, num2, digits, op) {
//得到处理为整数的对象
let n1 = this.toInteger(num1)
let n2 = this.toInteger(num2)
//算出公共的乘积的数。
let {
IntNum1, IntNum2, maxLen
} = this.handleCommonTimes(n1, n2)
//最大倍数
let maxTimes = Math.pow(10, maxLen)
//最终的值
let result = undefined;
switch (op) {
case 'add':
//相加的结果除以公积数就是最终结果
result = (IntNum1 + IntNum2) / maxTimes
break
case 'subtract':
//相减的结果除以公积数就是最终结果
result = (IntNum1 - IntNum2) / maxTimes
break
case 'multiply':
//乘法中每一项都乘以公积数,所以结果要除以公积数的平方
result = (IntNum1 * IntNum2) / (maxTimes * maxTimes)
break
case 'divide':
//除法,除数和被除数增加相同的倍数结果不变
result = (IntNum1 / IntNum2)
break
}
return result
}
//操作方法
add(val1, val2, digits) {
return this.operation(val1, val2, digits, 'add')
}
subtract(val1, val2, digits) {
return this.operation(val1, val2, digits, 'subtract')
}
multiply(val1, val2, digits) {
return this.operation(val1, val2, digits, 'multiply')
}
divide(val1, val2, digits) {
return this.operation(val1, val2, digits, 'divide')
}
}
// 使用
let calc = new HighPrecisionCalc ()
calc.add(1.22,1.33)
总体的思路:由于js无法精准计算带有小数点的值。所以先把小数点去掉(去掉小数点用字符串替换,如果使用乘以10的倍数,依然出现计算不精确问题) 实际的数学逻辑还是乘10的倍数。所以要计算出两个数值之间的最小公积数。让转化为整数的值乘以最小公积数,就一切好计算了 +法 最后相加的结果除以最小公积数 -法 最后相减的结果除以最小公积数 *法 结果除以公积数的平方 /法 直接除就好了