JavaScript进阶(二十七):JavaScript 浮点数精度计算_js 浮点数子算

最后

其实前端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一个复习的路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《前端开发四大模块核心知识笔记》

最后,说个题外话,我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在IT学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

//原型扩展方式,更喜欢面向对象的风格
Number.prototype.isEqual = function(number, digits){
digits = digits == undefined? 10: digits; // 默认精度为10
return this.toFixed(digits) === number.toFixed(digits);
}
console.log((1.0-0.7).isEqual(0.3)); //true


接下来,再来试试浮点数的运算,



console.log(1.79+0.12) //1.9100000000000001
console.log(2.01-0.12) //1.8899999999999997
console.log(1.01*1.3) //1.3130000000000002
console.log(0.69/10) //0.06899999999999999


解决方案 - **先升幂再降幂,同时辅以精度控制**



//加法函数,用来得到精确的加法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
//调用:accAdd(arg1,arg2)
//返回值:arg1加上arg2的精确结果
function accAdd(arg1,arg2){
var r1,r2,m;
try{r1=arg1.toString().split(“.”)[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(“.”)[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2))
return (arg1*m+arg2*m)/m
}
//给Number类型增加一个add方法,调用起来更加方便。
Number.prototype.add = function (arg){
return accAdd(arg,this);
}

//减法函数,用来得到精确的减法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
//调用:accSub(arg1,arg2)
//返回值:arg1减去arg2的精确结果
function accSub(arg1,arg2){
var r1,r2,m,n;
try{r1=arg1.toString().split(“.”)[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(“.”)[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2));
//last modify by deeka
//动态控制精度长度
n=(r1>=r2)?r1:r2;
return ((arg1*m-arg2*m)/m).toFixed(n);
}

//除法函数,用来得到精确的除法结果
//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精确结果
function accDiv(arg1,arg2){
var t1=0,t2=0,r1,r2;
try{t1=arg1.toString().split(“.”)[1].length}catch(e){}
try{t2=arg2.toString().split(“.”)[1].length}catch(e){}
with(Math){
r1=Number(arg1.toString().replace(“.”,“”))
r2=Number(arg2.toString().replace(“.”,“”))
return (r1/r2)*pow(10,t2-t1);
}
}
//给Number类型增加一个div方法,调用起来更加方便。
Number.prototype.div = function (arg){
return accDiv(this, arg);
}

//乘法函数,用来得到精确的乘法结果
//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用:accMul(arg1,arg2)
//返回值:arg1乘以arg2的精确结果
function accMul(arg1,arg2) {
var m=0,s1=arg1.toString(),s2=arg2.toString();
try{m+=s1.split(“.”)[1].length}catch(e){}
try{m+=s2.split(“.”)[1].length}catch(e){}
return Number(s1.replace(“.”,“”))*Number(s2.replace(“.”,“”))/Math.pow(10,m)
}
//给Number类型增加一个mul方法,调用起来更加方便。
Number.prototype.mul = function (arg){
return accMul(arg, this);
}


结果如下:



console.log(accAdd(1.79, 0.12)); //1.91
console.log(accSub(2.01, 0.12)); //1.89
console.log(accDiv(0.69, 10)); //0.069
console.log(accMul(1.01, 1.3)); //1.313


改造之后,可以愉快地进行浮点数加减乘除操作了~


### 三、整数精度问题


在 `Javascript` 中,整数精度同样存在问题,先来看看问题:


`JavaScript` 代码:



console.log(19571992547450991); //=> 19571992547450990
console.log(19571992547450991===19571992547450992); //=> true


同样的原因,在 `JavaScript` 中 `Number`类型统一按浮点数处理,整数是按最大54位来算最大`(253 - 1,Number.MAX_SAFE_INTEGER,9007199254740991)` 和最小`(-(253 - 1),Number.MIN_SAFE_INTEGER,-9007199254740991)` 安全整数范围的。所以只要超过这个范围,就会存在被舍去的精度问题。


当然这个问题并不只是在 `Javascript` 中才会出现,几乎所有的编程语言都采用了 `IEEE-745` 浮点数表示法,任何使用二进制浮点数的编程语言都会有这个问题,只不过在很多其他语言中已经封装好了方法来避免精度的问题,而 `JavaScript` 作为一门弱类型语言,从设计思想上就没有对浮点数有严格的数据类型,所以精度误差的问题就显得格外突出。


### 四、解决方案


#### 4.1 类库


通常这种对精度要求高的计算都应该交给后端去计算和存储,因为后端有成熟的库来解决这种计算问题。前端也有几个不错的类库:


##### 4.1.1 Math.js


`Math.js` 是专门为 `JavaScript` 和 `Node.js` 提供的一个广泛的数学库。它具有灵活的表达式解析器,支持符号计算,配有大量内置函数和常量,并提供集成解决方案来处理不同的数据类型  
 像数字,大数(超出安全数的数字),复数,分数,单位和矩阵。 功能强大,易于使用。


* [官网](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
* [GitHub](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)


##### 4.1.2 decimal.js


为 `JavaScript` 提供十进制类型的任意精度数值。


* [官网](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
* [GitHub](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)


##### 4.1.3 big.js


* [官网](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
* [GitHub](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)


这几个类库帮我们解决很多这类问题,不过通常我们前端做这类运算通常只用于表现层,应用并不是很多。所以很多时候,一个函数能解决的问题不需要引用一个类库来解决。


下面介绍各个更加简单的解决方案。


**整数表示**  
 对于整数,我们可以通过用`String`类型的表示来取值或传值,否则会丧失精度。


**格式化数字、金额、保留几位小数等**  
 如果只是格式化数字、金额、保留几位小数等可以查看[这里](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)。


### 五、延伸阅读


#### 5.1 IEEE 754 标准


`JavaScript` 里的数字是采用 `IEEE 754` 标准的 **64 位双精度浮点数**。该规范定义了浮点数的格式,对于64位浮点数在内存中的表示,最高1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体:



> 
> * 第0位:符号位, s 表示 ,0表示正数,1表示负数;
> * 第1位到第11位:储存指数部分, e 表示 ;
> * 第12位到第63位:储存小数部分(即有效数字),f 表示;
> 
> 
> 


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210714105342439.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3N1bmh1YXFpYW5nMQ==,size_16,color_FFFFFF,t_70)  
 其中:符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。


`IEEE 754`规定,有效数字第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字总是1.xx…xx的形式,其中xx…xx的部分保存在64位浮点数之中,最长可能为52位。因此,`JavaScript`提供的有效数字最长为53个二进制位(64位浮点的后52位+有效数字第一位的1)。


#### 5.2 toFixed()


浮点数运算的解决方案有很多,这里给出一种目前常用的解决方案, 在判断浮点数运算结果前对计算结果进行精度缩小,因为在精度缩小的过程总会自动四舍五入。


`toFixed()` 方法使用定点表示法来格式化一个数,会对结果进行四舍五入。语法为:



## Vue 面试题

1.Vue 双向绑定原理
2.描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
3.你是如何理解 Vue 的响应式系统的?
4.虚拟 DOM 实现原理
5.既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 DOM 进行 diff 检测差异?
6.Vue 中 key 值的作用?
7.Vue 的生命周期
8.Vue 组件间通信有哪些方式?
9.watch、methods 和 computed 的区别?
10.vue 中怎么重置 data?
11.组件中写 name 选项有什么作用?
12.vue-router 有哪些钩子函数?
13.route 和 router 的区别是什么?
14.说一下 Vue 和 React 的认识,做一个简单的对比
15.Vue 的 nextTick 的原理是什么?
16.Vuex 有哪几种属性?
17.vue 首屏加载优化
18.Vue 3.0 有没有过了解?
19.vue-cli 替我们做了哪些工作?
…
![](https://img-blog.csdnimg.cn/img_convert/3e749df52296b845644fa559f7ee2e71.webp?x-oss-process=image/format,png)

## 算法

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

1. 冒泡排序
2. 选择排序
3. 快速排序
4. 二叉树查找: 最大值、最小值、固定值
5. 二叉树遍历
6. 二叉树的最大深度
7. 给予链表中的任一节点,把它删除掉
8. 链表倒叙
9. 如何判断一个单链表有环
10. 给定一个有序数组,找出两个数相加为一个目标数
    ...
    ![](https://img-blog.csdnimg.cn/img_convert/980ef94cf20924d0bd62e371d34073cb.webp?x-oss-process=image/format,png)

>由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!有需要的程序猿(媛)可以帮忙点赞+评论666



. 快速排序
4. 二叉树查找: 最大值、最小值、固定值
5. 二叉树遍历
6. 二叉树的最大深度
7. 给予链表中的任一节点,把它删除掉
8. 链表倒叙
9. 如何判断一个单链表有环
10. 给定一个有序数组,找出两个数相加为一个目标数
    ...
    [外链图片转存中...(img-vHx5GKkM-1715824845250)]

>由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!有需要的程序猿(媛)可以帮忙点赞+评论666



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值