知识讲解
系统 + 全面
先说答案,0.1 + 0.2 不等于0.3 ,因为浮点数表示小数的时候有精度损失。
昨天我们已经说到,javascript中会使用52个bit表示小数部分。
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位。
有问题的同学请自行复习上一篇。
下面我们说说为什么浮点数无法精确表示小数。
二进制表示整数
十进制 | 二进制 | 2^2 | 2^1 | 2^0 |
4 | 2 | 1 | ||
0 | 0 | |||
1 | 1 | |||
2 | 1 | 0 | ||
3 | 1 | 1 | ||
4 | 1 | 0 | 0 | |
5 | 1 | 0 | 1 |
除二取余法
十进制换算二进制叫做
除二取余法
以5为例
5 / 2 = 2 余 1
2 / 2 = 1 余 0
1 / 2 = 0 余 1
上面算式你可以大家可以很清晰的看出来,余数连接起来就是5的二进制表示。
结论: 整数只要有足够的的二进制位可以连续表示
二进制表示小数
十进制 | 二进制 | 2^-2 | 2^-1 |
0.25 | 0.5 | ||
0 | 0 | ||
0.5 | 1 | ||
0.25 | 1 | 0 | |
0.75 | 1 | 1 |
可以发现随着使用二进制位数的增加精度会越来越高但是譬如五分之一 十分之一是永远无法表示的
乘二取整法
首先我们用0.75举例
0.75 * 2 = 1.5 取整 1 剩下 0.5
0.5 * 2 = 1 取整 1 剩下 0 运算结束
是不是所有整数部分连接起来正好是0.75的二进制部分
接着我们看看悲催的0.1
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
.....
我去BaBQ了感觉算不完了
其实0.2同理的大家可以试试
所以在有限精度内是无法取到五分之一和十分之一的。
这个就好像傻子切西瓜只能每次切一半,无论如何也不可能给你切除五分之一。
所以有限的52个bit是无法表示0.1这种数字的唯一的方法就是截取。
所以大家应该明白了吧。
面试攻略
精炼 + 系统 + 自洽
- 基本概念:Number是浮点数,表示小数会有精度损失。
- 递进:浮点数表示规则。
点评
- 红宝书都提过的超级经典题,也未必所有人都能答好。
- 初级:Number是浮点数,表示小数会有精度损失。
- 中级: 浮点数的表示规则
- 高级: 高精度运算、适合高精度的语言和解决方案