Day01 0.1+0.2 === 0.3 是否相等,你能答出这道前端面试题吗?js 浮点类型

379 阅读3分钟

Day01 JavaScript 浮点类型数字

背景

最近对每天坚持一件小事来了热情,想挑战下「每天打卡一个前端知识点,坚持 7 天」。路过的各位客观帮忙点个赞捧个场,你的鼓励是我不断分享的动力!

先抛一个问题 0.1+0.2 === 0.3 ?

我们在控制台输出下结果:

0.1+0.2 === 0.3 // false

结果显而易见,那么为什么会不相等呢?我们来复习下 JavaScript 中如何存储数字。

JavaScript 只有一种数字类型

JavaScript 只有一种数字类型,那就是浮点数字类型。所有的数字都是由 JavaScript 采用 IEEE754 标准定义的 64 位浮点格式表示数字,它能表示最大值(Number.MAX_VALUE)为 ±1.7976931348623157e+308,最小值(Number.MIN_VALUE)为 ±5e-324。 此格式用 64 位存储数值,其中 0 到 51 存储数字(片段),52 到 62 存储指数,63 位存储符号:

在 JavaScript 中如何存储 0.1、0.2、0.3 ?

复习完上文的知识点,我们来试着解析下 JavaScript 中如何存储小数和整数。 1、存储小数:乘 2 取整法。

// 对 0.1 进行乘 2 取整法
0.1*2 // 0.2 取整 0 余 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
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.2 进行乘 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
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

// 对 0.3 进行乘 2 取整法
0.3*2 // 0.6 取整 0 余 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
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
0.2*2 // 0.4 取整 0 余 0.4
...

再继续,what fk? 开始无限循环了。 0.1 的二进制:0.0001100110011001100110 0.2 的二进制:0.0011001100110011001100 0.3 的二进制:0.0100110011001100110011 我们可以使用 toString() 方法 输出 16 进制、8 进制、2 进制:

(0.1).toString(2) // '0.0001100110011001100110011001100110011001100110011001101'
(0.2).toString(2) // '0.001100110011001100110011001100110011001100110011001101'
(0.3).toString(2) // '0.010011001100110011001100110011001100110011001100110011'

所以,在 js 中,0.1+0.2 与 0.3 不相等。

2、存储整数:除2取余法。

// 对 5 进行除 2 取余法
5/2 // 2 余 1
2/2 // 1 余 0
1/2 // 0 余 1

// 对 9 进行除 2 取余法
9/2 // 4 余 1
4/2 // 2 余 0
2/2 // 1 余 0
1/2 // 0 余 1

// 对 3 进行除 2 取余法
3/2 // 1 余 1
1/2 // 0 余 1

所以用 2 进制表示 5、9、3 就是: 5 的二进制:101 9 的二进制:1001 3 的二进制:11

3、精度 小数的最大位数是 17,但是浮点运算并不总是 100% 准确。 在控制台输入 0.0001100110011001100110 ,我们看输出结果:

0.0001100110011001100110 
// 0.00011001100110011001

整数(不使用小数点或指数计数法)最多为 15 位。

9999999999999999
// 10000000000000000

总结和思考

Javascript 的数字类型是面试题中高频考察点。能够记住题目答案还不行,有些面试官会通过推演过程考察面试者的思维。所以你还等什么呢?学会了原理它不香吗?