LeetCode算法之小数相加

646 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情

🎉前言

先来看一道题: 0.1+0.2 === 0.3 吗?,相信有很多的小伙伴都知道不等于,因为计算机中计算小数相加不跟我们平时学的数学一样哦,那么 JavaScript 内部执行到底背着我们干了什么?

🚝 ​原因

其实这个问题不能完全怪 JavaScript,导致这样的问题是因为 JavaScript 中使用基于 IEEE 754 标准的浮点数运算,所以会产生舍入误差,也就是说所有遵循 IEEE 754 标准的语言进行浮点数运算的时候,都会有这个问题,可以称为 精度丢失问题。具体的产生原因我们不细讲,因为涉及到更底层的操作系统原理。

🚃 ​解决问题

假设有两个数相加,分别为 0.01 和 0.2,我们口算都知道等于 0.21,但是在 JS 中执行则等于 0.21000000000000002

在上面的解释中,我们既然知道了小数相加会出现精度丢失的问题,那我们该如何解决呢?在本篇文章中我们要实现解决的方案。

实现的原理很简单:就是将小数放大倍数变成整数后进行相加,得到结果再将它变回小数输出。

放大的倍数由什么决定呢?谁的小数点多就选谁。为什么呢?看下图:

image-20220428214951302.png

是不是结果就出来了,跟口算的结果一模一样。

先实现一个获取小数点有多少位的函数:

const getXiaoShuDian = number => {
    // 是整数的情况
    if (Math.floor(number) === number) {
        return 0;
    }
    const str = number.toString();
    const index = str.indexOf('.');
    const numLength = str.substring(index + 1).length;
    return numLength;
}

测试一下:

console.log(getXiaoShuDian(0.01)); // 2

主要逻辑代码:

const add = (num1, num2) => {
    let result = 0;
    const num1Len = getXiaoShuDian(num1);
    const num2Len = getXiaoShuDian(num2);
    const maxLen = num1Len > num2Len ? num1Len : num2Len; // 取两者之间比较长的一位
    const maxTimes = Math.pow(10, maxLen); // 放大的倍数
    result = (num1 * maxTimes + num2 * maxTimes) / maxTimes;
    return result;
}

测试一下:

console.log(add(0.01, 0.2)); // 0.21//对比
console.log(0.01 + 0.2); // 0.21000000000000002

🚎 ​拓展一下

既然 小数相加 都实现了,把其他的减法、除法是不是也可以以此类推呢。

代码实现:

class decimalCalculation {
​
    // 获取小数点后的位数
    getXiaoShuDian (number) {
        // 是整数的情况
        if (Math.floor(number) === number) {
            return 0;
        }
        const str = number.toString();
        const index = str.indexOf('.');
        const numLength = str.substring(index + 1).length;
        return numLength;
    }
​
    // 加法
    addition (num1, num2) {
        let result = 0;
        const num1Len = this.getXiaoShuDian(num1);
        const num2Len = this.getXiaoShuDian(num2);
        const maxLen = num1Len > num2Len ? num1Len : num2Len;
        const maxTimes = Math.pow(10, maxLen);
        result = (num1 * maxTimes + num2 * maxTimes) / maxTimes;
        return result;
    }
​
    // 减法
    subtraction (num1, num2) {
        let result = 0;
        const num1Len = this.getXiaoShuDian(num1);
        const num2Len = this.getXiaoShuDian(num2);
        const maxLen = num1Len > num2Len ? num1Len : num2Len;
        const maxTimes = Math.pow(10, maxLen);
        result = (num1 * maxTimes - num2 * maxTimes) / maxTimes;
        return result;
    }
​
    // 除法
    division (num1, num2) {
        let result = 0;
        const num1Len = this.getXiaoShuDian(num1);
        const num2Len = this.getXiaoShuDian(num2);
        const maxLen = num1Len > num2Len ? num1Len : num2Len;
        const maxTimes = Math.pow(10, maxLen);
        result = (num1 * maxTimes) / (num2 * maxTimes);
        return result;
    }
}

测试一下:

const calc = new decimalCalculation();
console.log(calc.subtraction(0.01, 0.2)); // -0.19
console.log(calc.division(0.01, 0.2)); // 0.05

✨总结

以上就是本次分享的全部内容~~

如果觉得文章写得不错,对你有所启发的,请不要吝啬 点个 关注 并在 评论区 留下你宝贵的意见哦~~😃