【js/ts】js/ts高精度加减乘除函数

20 篇文章 0 订阅

加法

/**
 * 高精度加法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 被加数
 * @param {string|number} b - 加数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const add = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算和
    const sum = numA + numB;
    let resultInt = (sum / factor).toString();
    let resultDec = (sum % factor).toString().padStart(maxDecLen, '0');
    // 去除小数部分尾部多余的零
    resultDec = resultDec.replace(/0+$/, '');
    // 拼接结果,处理小数部分
    let result = resultInt;
    if (resultDec.length > 0) {
        result += '.' + resultDec;
    }
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(result) === 0) result = '0';
    return result;
};

减法

/**
 * 高精度减法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 被减数
 * @param {string|number} b - 减数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const subtract = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算差
    const diff = numA - numB;
    const isNegative = diff < 0n;
    const absDiff = isNegative ? -diff : diff;
    // 计算整数和小数部分
    let resultInt = (absDiff / factor).toString();
    let resultDec = (absDiff % factor).toString().padStart(maxDecLen, '0');
    // 去除小数部分尾部多余的零
    resultDec = resultDec.replace(/0+$/, '');
    // 拼接结果,处理小数部分
    let result = resultInt;
    if (resultDec.length > 0) {
        result += '.' + resultDec;
    }
    // 添加负号(如果需要)
    if (isNegative) {
        result = '-' + result;
    }
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(result) === 0) result = '0';
    return result;
};

乘法

/**
 * 高精度乘法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 乘数
 * @param {string|number} b - 被乘数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const multiply = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    // 计算乘积
    const product = numA * numB;
    let result = product.toString();
    // 计算小数位数
    const totalDecLen = decA.length + decB.length;
    // 处理小数部分
    if (totalDecLen > 0) {
        const integerLen = result.length - totalDecLen;
        if (integerLen <= 0) {
            result = '0.' + '0'.repeat(-integerLen) + result;
        } else {
            result = result.slice(0, integerLen) + '.' + result.slice(integerLen);
        }
        result = result.replace(/(\.[0-9]*?)0+$/, '$1').replace(/\.$/, '');
    } else {
        result = result || '0';
    }
    return result;
};

除法

/**
 * 高精度除法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} dividend - 被除数
 * @param {string|number} divisor - 除数
 * @param {number} precision - 结果保留的小数位数,默认为 28
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字或除数为零,抛出错误
 */
export const highPrecisionDivision = (dividend, divisor, precision = 28) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    dividend = validateNumber(dividend);
    divisor = validateNumber(divisor);
    // 将小数点移动到末尾,统一处理
    const moveDecimal = (num) => {
        const [intPart, decPart] = num.split('.');
        return intPart + (decPart || '');
    };
    // 移动小数点
    const movedDividend = moveDecimal(dividend);
    const movedDivisor = moveDecimal(divisor);
    // 转换为 BigInt 处理,保证精度
    const numDividend = BigInt(movedDividend);
    const numDivisor = BigInt(movedDivisor);
    // 计算商和余数
    let quotient = (numDividend / numDivisor).toString();
    // 处理小数部分
    if (precision > 0) {
        const [intPart, decPart = ''] = quotient.split('.');
        let decimalPart = decPart.padEnd(precision, '0');
        decimalPart = decimalPart.slice(0, precision);
        quotient = `${intPart}.${decimalPart}`;
    } else {
        quotient = quotient.split('.')[0]; // 只取整数部分
    }
    // 去除尾部多余的零
    quotient = quotient.replace(/\.?0+$/, '');
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(quotient) === 0) quotient = '0';
    return quotient;
};
add(0.1, "0.3") // 0.4
add(-0.1, "0.3") // 0.2
add(0.1, 0.3) // 0.4
add(0.1687486415614614, 0.3) // 0.4687486415614614
add("5614", "999999999999999991454444444444444444444444444444") // 999999999999999991454444444444444444444444450058


subtract("5", "3") // 2
subtract("-5", "3") // 8
subtract(123.45, "67.89") // 55.56
subtract('561456.514614', "679") // 560777.514614
subtract("1000000000000000000000000000000", "1") // 999999999999999999999999999999


multiply("123", "456") // 56088
multiply("-123", "456") // -56088
multiply(0.52, "67.89") // 35.3028
multiply(0.548568482, "0.5688974989") // 0.3120792373851696698
multiply("1000000000000000000000000000000", "1") // 1000000000000000000000000000000


highPrecisionDivision(10,2) // 5
highPrecisionDivision(-10,2) // -5
highPrecisionDivision(0.456,0.00458) // 0.1249999988609375028980608135
highPrecisionDivision('0.456',0.08) // 0.1249999988609375028980608135
highPrecisionDivision(42424,424732545354332543543) // 0.0000000000000000998840339975

TS封装版本

/**
 * 高精度数学运算函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 第一个操作数
 * @param {string|number} b - 第二个操作数
 * @param {string} operator - 运算符 ('+', '-', '*', '/')
 * @param {number} precision - 除法结果保留的小数位数,默认为 28
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字或除数为零,抛出错误
 */
export const highPrecisionOperation = (a: string | number, b: string | number, operator: string, precision = 28): string => {
    // 验证输入是否为有效的数字
    const validateNumber = (num: string | number): string => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(Number(num)))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为 BigInt 处理,保证精度
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算结果
    let result: string;
    switch (operator) {
        case '+': {
            const sum = numA + numB;
            let resultInt = (sum / factor).toString();
            let resultDec = (sum % factor).toString().padStart(maxDecLen, '0');
            resultDec = resultDec.replace(/0+$/, ''); // 去除尾部多余的零
            result = resultInt + (resultDec.length > 0 ? '.' + resultDec : '');
            break;
        }
        case '-': {
            const diff = numA - numB;
            const isNegative = diff < 0n;
            const absDiff = isNegative ? -diff : diff;
            let resultInt = (absDiff / factor).toString();
            let resultDec = (absDiff % factor).toString().padStart(maxDecLen, '0');
            resultDec = resultDec.replace(/0+$/, ''); // 去除尾部多余的零
            result = resultInt + (resultDec.length > 0 ? '.' + resultDec : '');
            if (isNegative) {
                result = '-' + result;
            }
            break;
        }
        case '*': {
            const product = numA * numB;
            result = product.toString();
            // 处理小数部分
            if (maxDecLen > 0) {
                const integerLen = result.length - maxDecLen;
                if (integerLen <= 0) {
                    result = '0.' + '0'.repeat(-integerLen) + result;
                } else {
                    result = result.slice(0, integerLen) + '.' + result.slice(integerLen);
                }
                result = result.replace(/(\.[0-9]*?)0+$/, '$1').replace(/\.$/, '');
            } else {
                result = result || '0';
            }
            break;
        }
        case '/': {
            const quotient = (numA / numB).toString();
            const [intPart, decPart = ''] = quotient.split('.');
            let decimalPart = decPart.padEnd(precision, '0');
            decimalPart = decimalPart.slice(0, precision);
            result = `${intPart}.${decimalPart}`;
            result = result.replace(/\.?0+$/, ''); // 去除尾部多余的零
            break;
        }
        default:
            throw new Error(`Unsupported operator: ${operator}`);
    }
    // 如果结果是负零或零,需要转换成 '0'
    if (parseFloat(result) === 0) result = '0';
    return result;
};

使用方法

const resultAdd = highPrecisionOperation('123.456', '789.012', '+');
console.log('加法结果:', resultAdd);

const resultSubtract = highPrecisionOperation('123.456', '789.012', '-');
console.log('减法结果:', resultSubtract);

const resultMultiply = highPrecisionOperation('123.456', '789.012', '*');
console.log('乘法结果:', resultMultiply);

const resultDivision = highPrecisionOperation('123.456', '789.012', '/', 5);
console.log('除法结果:', resultDivision);

在这里插入图片描述
感谢你的阅读,如对你有帮助请收藏+关注!
只分享干货实战精品从不啰嗦!!!
如某处不对请留言评论,欢迎指正~
博主可收徒、常玩QQ飞车,可一起来玩玩鸭~

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

★雨 潇★

谢谢您的鼓励,我会继续努力的~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值