美文网首页
前端面试底气之0.1+0.2=?

前端面试底气之0.1+0.2=?

作者: 跨栏高手东莞仔 | 来源:发表于2021-04-14 09:15 被阅读0次

    转自:掘金 - 红尘炼心

    https://juejin.cn/post/6927217000112455687

    去互联网金融或电商行业的公司面试时,一般都会遇到类似“0.1+0.2等于0.3吗?”这道题,对于非科班出身的前端人是一道送命题,有些知道0.1+0.2不等于0.3,但是继续深问为什么,就无法很清晰地回答。

    本专栏总结一下回答0.1+0.2不等于0.3的思路,在回答之前要先弄清楚0.1+0.2的计算过程

    0.1+0.2的计算过程计算过程

    1、十进制转成二进制

    在JS内部所有的计算都是以二进制方式计算的。所以运算0.1+0.2时要先把0.1和0.2从十进制转成二进制。

    0.1转化成二进制的算法:

    0.1*2=0.2======取出整数部分0

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    接下来会无限循环

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    所以0.1转化成二进制是:0.0001 1001 1001 1001......

    0.2转化成二进制的算法:

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    接下来会无限循环

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    所以0.2转化成二进制是:0.0011 0011 0011 0011......

    这里要注意0.1和0.2转成的二进制是无穷的。另外在现代浏览器中是用浮点数形式的二进制来存储二进制,所以还要把上面所转化的二进制转成浮点数形式的二进制。

    2、转成浮点数

    浮点数分为单精度对应32位操作系统和双精度对应64位操作系统。目前的操作系统大多是64位操作系统,故这里只解释一下二进制如何转成双精度浮点数的二进制。

    双精度浮点数用1位表示符号位,11位表示指数位,52位表示小数位,如下图所示:

    符号位:正数为0,负数为1;

    指数位:阶数+偏移量,阶数是:2^{e-1}-1,e为阶码的位数。偏移量是把小数点移动到整数位只有1时移动的位数,正数表示向左移,负数表示向右移;

    小数位:即二进制小数点后面的数。

    接下来把0.1转成的二进制0.0001100110011001.....转成浮点数形式的二进制。

    先要把小数点移动到整数位只有1,要向右移动4位,故偏移量为−4,通过指位数的计算公式2^{11-1}-1-4 = 1019,把1019转成二进制为1111111011,不够11位要补零,最终得出指位数为01111111011;

    小数位为100110011001......,因为小数位只能保留52位,第53位为1故进1。

    转换结果如下图所示:

    同理,再把0.2转成的二进制0.00110011 00110011.......转成浮点数形式的二进制,转换结果如下图所示:

    浮点数相加

    浮点数相加时,需要先比较指位数是否一致,如果一致则小数位直接相加,如果不一致,要先把指位数调成一致的,指位数小的向大的调整。

    为了行文方便,把0.1转成的浮点数称为为0.1,把0.2转成的浮点数称为0.2。

    0.1的指数位是1019,0.2的指数位是1020。故要把0.1的指数位加1,即把0.1的小数点向左移动1位,另外浮点数的整数位固定为1,过程如下所示

    1.1001100110011001100110011001100110011001100110011010  原先0.11001100110011001100110011001100110011001100110011010  移动后  0.1100110011001100110011001100110011001100110011001101  将小数的第53位舍去,因为为0故不需进1复制代码

    导致0.1的小数位变成如下所示:

    现在0.1和0.2的指数位相同了,把小数位直接相加。

    1100110011001100110011001100110011001100110011001101 0.1的小数位+  1001100110011001100110011001100110011001100110011010 0.2的小数位=  10110011001100110011001100110011001100110011001100111

    会发现现在的小数位多出了一位,超出了52位,故要把小数位最后一位截掉,小数位最后一位是1,故要进1,如下所示:

    10110011001100110011001100110011001100110011001100111(截取前)

    1011001100110011001100110011001100110011001100110100(截取后)

    截掉小数位的最后一位相当把小数点向左移了一位,故指数位要加1,此时的指数是0.2的指数1020,加1后变成1021,转成二进制为01111111101,那么相加后的浮点数如下所示:

    浮点数转成十进制

    相关文章

      网友评论

          本文标题:前端面试底气之0.1+0.2=?

          本文链接:https://www.haomeiwen.com/subject/rlclrhtx.html