一、前言
工作中经常遇到用户输入后实时计算结果,比如输入单价和数量后自动计算总价,部分情况下会出现丢失精度的问题。解决方式为将小数放大为整数,计算完后再缩小。
二、解决
/*
* 加法
* add(0.123 , 1.4567 , 10.56789)
*/
function add(...val) {
let sum = 0,
maxDecimalLength = getMaxDecimalLength(...val)
val.forEach((x, index) => {
// 所有数值转为整数计算
sum += Math.round(x * Math.pow(10, maxDecimalLength))
})
return sum / Math.pow(10, maxDecimalLength)
}
/*
* 减法
* subtract(0.123 , 1.4567 , 10.56789)
*/
function subtract(...val) {
let sum,
maxDecimalLength = getMaxDecimalLength(...val)
val.forEach((x, index) => {
let nurVal = Math.round(x * Math.pow(10, maxDecimalLength));
if (index === 0)
sum = nurVal
else
sum -= nurVal
})
return sum / Math.pow(10, maxDecimalLength)
}
/*
* 乘法
* multiply(0.123 , 1.4567 , 10.56789)
*/
function multiply(...val) {
let sum,
decimalLengthSum = 0
val.forEach((x, index) => {
// 获取当前小数位长度
let decimalLength = getMaxDecimalLength(x)
// 将当前数变为整数
let nurVal = Math.round(x * Math.pow(10, decimalLength));
decimalLengthSum += decimalLength
if (index === 0)
sum = nurVal
else
sum *= nurVal
})
return sum / Math.pow(10, decimalLengthSum)
}
/*
* 除法
* divide(0.123 , 1.4567 , 10.56789)
*/
function divide(...val) {
let sum = 0,
decimalLengthSum = 0
val.forEach((x, index) => {
// 获取当前小数位长度
let decimalLength = getMaxDecimalLength(x)
// 将当前数变为整数
let nurVal = Math.round(x * Math.pow(10, decimalLength));
if (index === 0) {
decimalLengthSum = decimalLength
sum = nurVal
} else {
decimalLengthSum -= decimalLength
sum /= nurVal
}
})
return sum / Math.pow(10, decimalLengthSum)
}
/*
* 获取小数位数
*/
function getMaxDecimalLength(...val) {
// 最大小数位长度
let maxDecimalLength = 0
val.forEach((x) => {
const strVal = x.toString(),
dotIndex = strVal.indexOf('.')
if (dotIndex > -1) {
// 获取当前值小数位长度
let curDecimalLength = strVal.length - 1 - dotIndex
if (curDecimalLength > maxDecimalLength) {
maxDecimalLength = curDecimalLength
}
}
})
return maxDecimalLength
}