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

11 篇文章 0 订阅

科学计数法

假设有两个数字

220000000000 和 22000000000

一眼看过去好像很难比较出大小

但是使用科学计数法就非常容易进行比较
2.2 ∗ 1 0 11 2.2 ∗ 1 0 10 2.2*10^{11}\\ 2.2*10^{10} 2.210112.21010

IEEE 754浮点数表示

Javascript是使用双精度浮点数表示的。

  • sign:符号位 1表示数字为负数,0表示为正数 (1位)
  • exponent:阶码 (11位)
  • mantissa: 尾数 (52位)
  • 总共64位

在这里插入图片描述

看不懂就对了,我刚开始也看不懂,估计很快也忘了

举个🌰

整数11,用科学计数法表示

在这里插入图片描述

  1. 这是一个正数,sign:符号位表示为 0

在这里插入图片描述

右上角1次幂就是阶码:exponent,但是还需要加上一个值1023,书上叫偏置值

主要是因为
在这里插入图片描述

能够正常使用的数有
0111111111 1 2 = 1023 1000000000 0 2 = − 1024 011 1111 1111_2=1023\\ 100 0000 0000_2=-1024 011111111112=1023100000000002=1024
为了方便进行浮点数之间的数学比较,需要保证阶码总是为无符号数

有符号数转成无符号数进行比较效率跟整型(如C语言的int类型)相同

所以这里要加上一个偏置值,保证exponent的值总是>0

11位数字的范围明明是1023~ -1024,又要保证其>0,为什么添加的偏置值只有1023 ?

主要是因为111 1111 1111000 0000 0000是两种特殊情况,排除在外,所以只需要+1023就能保证表示范围>0

(图中的K就是偏置值Bias)

在这里插入图片描述

综上exponent的值为 100 0000 0000

3.mantissa: 尾数

(有些书上fraction也是一个意思)

在这里插入图片描述

假设我们只表示100,1100,11111这样的数字,它们的科学计数法都是以1.xxx开头的,这样的话,1.xxx部分就可以省去,仅表示小数点.后面的数字即可

综合以上整数11可以表示为
在这里插入图片描述

200 300 这样的数字如何表示?

事实上,计算机的数字都是以二进制形式存储的,刚才的11在二进制表示是3。也就是说,刚才存储的实际上是十进制3而不是十进制11

意思就是只需要将刚才的

在这里插入图片描述

改成2,就是在计算机中存储3的浮点数值。

为什么0.1 + 0.2 不等于 0.3

Js中数字都采用双精度浮点数表示

首先要将0.1转成二进制形式表示,小数转成二进制的方式就是不断*2,结果如果>1,说明该位需要用1表示,然后保留小数部分,继续乘直到得到0

在这里插入图片描述

0.1的二进制表示

在这里插入图片描述

熟悉的科学计数法表示

在这里插入图片描述

尾数(mantissa)是有限位数,能存放52位数字。

在这里插入图片描述

注意高亮的部分,52位后的部分就进行舍入,舍入类似于十进制的四舍五入,1则进位,0则不变。

这里发生的实际上是一个向上舍入,也就是得到的数字会比真实的数字大

在这里插入图片描述

再来计算它的阶码

在这里插入图片描述

0.1的最终存储形式为

在这里插入图片描述

0.2也是类似的,尾数部分第53位也是1,意味着也发生了向上舍入

在这里插入图片描述

计算0.1+0.2

科学计数法表示两个数
在这里插入图片描述

调整0.1的表示方法,跟0.2对齐

在这里插入图片描述

进行运算

在这里插入图片描述

计算结果

在这里插入图片描述

同样是超出了52位,而且第53位为1,说明真正存储的时候会发生向上舍入

在这里插入图片描述

为了计算0.1+0.2整整发生了3次向上舍入!

这也是为什么控制台打印得到的结果会比实际结果大。

在这里插入图片描述

循环永远不会结束

for(let i = 0; i = 9007199254740992; i++){
    //never stop
}

这个循环将永远不会结束。

javascript中有一个Number.MAX_SAFE_INTEGER打印的结果是9007199254740991 (2⁵³−1)

可以看到,超出这个最大安全整型,就会出现一些奇怪的事情

在这里插入图片描述

9007199254740991浮点表示

在这里插入图片描述

注意,尾数部分全为1

将其转成科学计数法

在这里插入图片描述

2⁵³−1实际上就是尾数部分,是尾数部分能够表示的极限了,因此9007199254740991这个数值就是使用双精度浮点数能表示最大的数值。

特殊情况NaN Infinity

刚才计算exponent的时候偏置值并不是1025,主要是因为另外两个独立的存在

其中一个独立的存在是阶码全为1的情况

NaN

在这里插入图片描述

Infinity无穷大

在这里插入图片描述

另一个阶码全为0的情况不多做讨论,书上称为非规格化数,它提供一种表示0的方法

符号位为1,其他位都为0,可以表示负-0.0

符号位为0,其他位都为0,可以表示+0.0


详情参考
《深入理解计算机系统》第二章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值