JS精度丢失问题

// console.log('1.43', toDecimal(0.95 * 1.5));
// console.log('2.87', toDecimal(3.82 * 0.75));
// console.log('2', toDecimal(9.5 * 0.21));
// console.log('2', toDecimal(9.5 * 0.021));
// console.log('8.08', toDecimal(9.5 * 0.85));
// console.log('2.76', toDecimal(0.95 * 2.9));
// console.log('1.45', toDecimal(1.444999999999));
// console.log('1.44', toDecimal(1.444699999999));
// console.log('1.2', toDecimal(1.2));
// console.log('1.0', toDecimal(1.0));
// console.log('1.11', toDecimal(1.11));
// console.log('1.10', toDecimal(1.10));
// console.log('1.111', toDecimal(1.111));
// console.log('1.110', toDecimal(1.110));
// console.log('5.5', toDecimal(5.5, 0));
// console.log('5.6', toDecimal(5.6, 0));
// console.log('5.4999999', toDecimal(5.4999999, 0));
// console.log('5', toDecimal(5, 0));
// console.log('0.01', toDecimal(0.01, 2));
// console.log('0', toDecimal(0.000001, 0));
// console.log('0', toDecimal(0.000001, 2));
// console.log('0', toDecimal(0, 2));

/**
 * 保留任意位小数
 * @param number 数值
 * @param precision 保留小数位数
 * @param toFixed 是否四舍五入
 * @param isNumber 返回值是否为数值类型
 * @returns {any}
 */
export function toDecimal(number, precision = 2, toFixed = true, isNumber = true) {
    (number == undefined || number == null || number == "" || Number.isNaN(number)) && (number = 0)
    let newNumber = String(number);
    let arr = newNumber.split(".");
    arr[0] == '' && (arr[0] = 0);
    // 如果不是小数,补充对应的0
    if (arr.length === 1) {
        return isNumber ? Number(newNumber) : (newNumber + "." + "0".repeat(precision))
    } else {
        // 如果是小数 但位数比要保留的位数少 也是要补0
        if (arr[1].length <= precision) {
            return isNumber ? Number(newNumber) : (newNumber + "0".repeat(precision - arr[1].length));
        } else {

            let intNumber = parseInt(arr[0]);// 整数部分

            let decimal = String(arr[1]);// 所有小数部分

            let frontDecimal;//有效小数部分

            if (Number(decimal) == 0) {
                frontDecimal = 0
            } else {
                if (decimal.length <= precision) {
                    //小数量小于所需小数位
                    frontDecimal = decimal;
                } else {
                    //小数量大于所需小数位
                    frontDecimal = (precision > 0 ? (decimal.substr(0, precision)) : 0) * 1;

                    let moreDecimal = parseInt(decimal.substr(precision, 1));

                    let spliceNumber = decimal.substr(precision, 5);
                    if (spliceNumber === '49999') {
                        moreDecimal += 1;
                    }
                    if (moreDecimal >= 5) {
                        frontDecimal += 1;
                    }
                    //判断小数部位是否需要进位 类似于19.996 保留2位小数 就是20.00
                    if (frontDecimal === Math.pow(10, precision)) {
                        frontDecimal = '0'.repeat(precision)
                        intNumber += 1;
                    }
                    //处理 0.015 0.009 保留的小数中有0出现的情况
                    if (String(frontDecimal).length < precision) {
                        frontDecimal = '0'.repeat(precision - String(frontDecimal).length) + frontDecimal
                    }
                }
            }

            return isNumber ? Number(`${intNumber}.${frontDecimal}`) : `${intNumber}.${frontDecimal}`
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值