「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
前言
先来说结论:0.1 + 0.2 !== 0.3
很多面经中其实都有类似的题目,给出的答案是 Number类型运算存在精度丢失的问题,因此会造成 0.1 + 0.2 !== 0.3
- 如果你在面试中这样回答,然后候面试过接着问 0.5 + 0.75 === 1.25 吗?
- 在控制台中测试结果两者是相等的,这又该如何解释呢?带着疑问往下看
在JS中Number类型的表示方法
根据国际标准 IEEE 754 读作: I treble E 754,在JS中所有的数字都是用64位二进制浮点数的形式表示的
- 第1位:符号位(sign),
0表示正数,1表示负数 - 第2-12位(共11位):指数位(exponent)
- 第13-64位(共52位):小数部分(fraction)
- 表示方法:(-1)^sign * fraction * 2^exponent
0.101 (二进制) 可以表示为 -1^0 * 1.01 * 2^-1
根据这个标准,就可以确定JS中整数的有效范围是 -(2^53 - 1) ~ 2^53 - 1 [Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],为什么可以是53次方,因为公式中整数部分一定是1,所以可以省略,因此就多了一位
我们平时使用的数字是十进制,在JS中会按照这个标准转为对应的二进制数
知道了这个概念后,看一下十进制是怎么转为二进制的
十进制数转二进制
一般采取的策略是,整数部分和小数部分分开转换然后再合并
整数部分:除二取余法
- 十进制13转二进制1101
小数部分:乘二取整法
- 十进制0.3转二进制是一个无限循环小数 0.01001100110011001...
总结
知道了上面的概念后,现在就可以很好的回答一开始的问题
- 0.1 和 0.2 在计算时被转为二进制,小数部分利用乘二取整法转换后都是无限循环小数,因此相加以后存在精度丢失的问题
- 0.5 和 0.75 转为二进制的过程中,小数部分乘二取整最终变成
0,因此不存在精度丢失