js浮点数精确计算(加、减、乘、除)


在JavaScript中,由于浮点数在内存中的表示方式(基于IEEE 754标准),直接进行加、减、乘、除运算时可能会遇到精度问题。为了进行精确的浮点数计算,我们可以使用一些库,如`decimal.js`或`bignumber.js`,但如果你希望不使用任何外部库,并且只是需要处理一些基本的精度问题,可以通过将浮点数转换为整数进行计算,然后再转换回浮点数来避免一些常见的精度问题。

以下是一个简单的示例,展示了如何在不使用外部库的情况下,通过转换浮点数到整数(乘以一个倍数),然后进行运算,最后再转换回浮点数(除以相应的倍数)来实现加、减、乘、除的精确计算:


function preciseAdd(num1, num2) {
    // 将两个浮点数乘以10的倍数,转为整数进行相加
    // 这里倍数根据实际情况选择,可能需要动态计算以避免溢出
    const factor = Math.pow(10, Math.max(decimalPlaces(num1), decimalPlaces(num2)));
    return (num1 * factor + num2 * factor) / factor;
}

function preciseSubtract(num1, num2) {
    const factor = Math.pow(10, Math.max(decimalPlaces(num1), decimalPlaces(num2)));
    return (num1 * factor - num2 * factor) / factor;
}

function preciseMultiply(num1, num2) {
    // 乘法时,两个数的最大小数位数之和即为结果的小数位数
    const factor = Math.pow(10, decimalPlaces(num1) + decimalPlaces(num2));
    return (num1 * factor * num2 * factor) / (factor * factor);
}

function preciseDivide(num1, num2) {
    // 除法时,取两个数中小数位数较大的值作为结果的小数位数
    const factor = Math.pow(10, Math.max(decimalPlaces(num1), decimalPlaces(num2)));
    return (num1 * factor) / (num2 * factor);
}

// 辅助函数,用于计算一个浮点数的小数位数
function decimalPlaces(num) {
    const match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
    if (!match) { return 0; }
    if (!match[2]) { // 没有指数部分
        return match[1] ? match[1].length : 0;
    }
    return Math.abs(parseInt(match[2], 10)) - (match[1] ? match[1].length : 0);
}

// 示例使用
console.log(preciseAdd(0.1, 0.2)); // 输出: 0.3
console.log(preciseSubtract(0.3, 0.1)); // 输出: 0.2
console.log(preciseMultiply(0.1, 0.2)); // 输出: 0.02
console.log(preciseDivide(0.2, 0.1)); // 输出: 2

请注意,这种方法并不完美,特别是当处理非常大的浮点数或需要非常高精度时。此外,`decimalPlaces`函数用于估算小数位数,它可能无法在所有情况下都完全准确。对于更复杂或高精度的需求,建议使用专门的库,如`decimal.js`或`bignumber.js`。