JavaScript中 0.1+0.2为什么不等于0.3

初学JavaScript最让人头疼的莫过于两件事:
一、浮点数的计算;
二、异步获取数据;
今天咱们就来了解一下 这两个大问题其中的浮点数计算问题

一、浮点数计算

例如经典的0.1+0.2问题
按照常规的答案为0.3,的确,在小学课本以及大学课本的答案都是0.3;
在各大语言(java、php、python、go、c等等)答案也是0.3;
为什么单单在JavaScript语言中就不是了,曾经我就这个答案骂过*****(你们懂得)

言归正传,开始分析问题
搞清楚这个问题前要懂得两个基本知识点
1、十进制转化二进制
2、数字在JavaScript内部是如何存储的

转化二进制是各种高级语言到最原生的机器代码必经之路(毕竟电脑只认识0和1),
十进制转化二进制的方法在不同语言中各不相同,但是逻辑思想是一致的
上学的时候老师教过转化方法

下面就手动撸下0.1、0.2转化成二进制的过程(此处是重点,打个✳标记)
整数部分 除二倒取余,
小数部分 乘二取整
二进制结果只包含0和1两个数字
十进制100转化成二进制 结果1100100
过程:
100/2=50 (余数0)
50/2=25  (余数0)
25/2=12  (余数1)
12/2=6   (余数0)
6/2=3    (余数0)
3/2=1    (余数1)
1/2=0    (余数1)

十进制0.2转化成二进制 结果0.001100110011.....(无限循环小数)
过程
0.2*2=0.4   (取整数 0  余0.4)
0.4*2=0.8   (取整数 0  余0.8)
0.8*2=1.6   (取整数 1  余0.6)
0.6*2=1.2   (取整数 1  余0.2)
0.2*2=0.4   (取整数 0  余0.4)
0.4*2=0.8   (取整数 0  余0.8)
0.8*2=1.6   (取整数 1  余0.6)
0.6*2=1.2   (取整数 1  余0.2)
......001100110011...

十进制0.1转化成二进制 结果0.0001100110011....(无限循环小数)
过程
0.100*2=0.2   (取整数 0  余0.2)
0.200*2=0.4   (取整数 0  余0.4)
0.400*2=0.8   (取整数 0  余0.8)
0.800*2=1.6   (取整数 1  余0.6)
0.600*2=1.2   (取整数 1  余0.2)
0.200*2=0.4   (取整数 0  余0.4)
0.400*2=0.8   (取整数 0  余0.8)
0.800*2=1.6   (取整数 1  余0.6)
0.600*2=1.2   (取整数 1  余0.2)
......001100110011...

JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此
第1位:符号位,0表示正数,1表示负数
第2位到第12位(共11位):指数部分
第13位到第64位(共52位):小数部分(即有效数字)

上面公式是正常情况下(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。
精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-253到253,都可以精确表示。

显然0.1和0.2在转化成二进制时时无限循环小数,在53位小数后被中断,后面的已经被忽略掉 在转换过程中就造成了不精确的数
所以两个不精确的数相加后结果必然不等于3
如何避免这种情况的发生呢
通常的解决办法是将0.110+0.210,再将结果除10 就是正确的3

验证
0.1*10=1
1转换成二进制 结果为01
1/2=0(余数是1)

0.2*10=2
2转换成二进制 结果为10
2/2=1 (余数0)
1/2=0  (余数1)

二进制 01+10=11
二进制转化十进制 1*2^0+1*2^1=3
3/10=0.3

二、解决异步

promise
async。。。await
回掉函数等等
后面篇章在详解

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一只倒霉的猫

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值