经典面试题:0.1 + 0.2 === 0.3 吗?

542 阅读2分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

前言

先来说结论:0.1 + 0.2 !== 0.3

图片.png

很多面经中其实都有类似的题目,给出的答案是 Number类型运算存在精度丢失的问题,因此会造成 0.1 + 0.2 !== 0.3

  • 如果你在面试中这样回答,然后候面试过接着问 0.5 + 0.75 === 1.25 吗?

图片.png

  • 在控制台中测试结果两者是相等的,这又该如何解释呢?带着疑问往下看

在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中会按照这个标准转为对应的二进制数

知道了这个概念后,看一下十进制是怎么转为二进制的

十进制数转二进制

一般采取的策略是,整数部分和小数部分分开转换然后再合并

整数部分:除二取余法

图片.png

  • 十进制13转二进制1101

图片.png

小数部分:乘二取整法

图片.png

  • 十进制0.3转二进制是一个无限循环小数 0.01001100110011001...

图片.png

总结

知道了上面的概念后,现在就可以很好的回答一开始的问题

  • 0.1 和 0.2 在计算时被转为二进制,小数部分利用乘二取整法转换后都是无限循环小数,因此相加以后存在精度丢失的问题
  • 0.5 和 0.75 转为二进制的过程中,小数部分乘二取整最终变成0,因此不存在精度丢失