一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第28天,点击查看活动详情
🎉前言
先来看一道题: 0.1+0.2 === 0.3 吗?,相信有很多的小伙伴都知道不等于,因为计算机中计算小数相加不跟我们平时学的数学一样哦,那么 JavaScript 内部执行到底背着我们干了什么?
🚝 原因
其实这个问题不能完全怪 JavaScript,导致这样的问题是因为 JavaScript 中使用基于 IEEE 754 标准的浮点数运算,所以会产生舍入误差,也就是说所有遵循 IEEE 754 标准的语言进行浮点数运算的时候,都会有这个问题,可以称为 精度丢失问题。具体的产生原因我们不细讲,因为涉及到更底层的操作系统原理。
🚃 解决问题
假设有两个数相加,分别为 0.01 和 0.2,我们口算都知道等于 0.21,但是在 JS 中执行则等于 0.21000000000000002。
在上面的解释中,我们既然知道了小数相加会出现精度丢失的问题,那我们该如何解决呢?在本篇文章中我们要实现解决的方案。
实现的原理很简单:就是将小数放大倍数变成整数后进行相加,得到结果再将它变回小数输出。
放大的倍数由什么决定呢?谁的小数点多就选谁。为什么呢?看下图:
是不是结果就出来了,跟口算的结果一模一样。
先实现一个获取小数点有多少位的函数:
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
✨总结
以上就是本次分享的全部内容~~
如果觉得文章写得不错,对你有所启发的,请不要吝啬 点个 赞 和 关注 并在 评论区 留下你宝贵的意见哦~~😃