上一篇:3600万中国人在抖音“上清华”

来自:掘金,作者:红尘炼心

链接: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;

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

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

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

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

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

转换结果如下图所示:

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

浮点数相加

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

为了行文方便,把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的指数1021 ,加1后变成1021 ,转成二进制为01111111101 ,那么相加后的浮点数如下所示:

浮点数转成十进制

二进制浮点数计算结束后,把结果(二进制的浮点数)转成十进制,其转换公式为 ,s是符号位为0或1,e为浮点数指数位转成十进制的值,i表示小数位从左到右的位数,第一位 i=1 ,表示每一位的值为0或1。

那么按着公式把二进制的浮点数转成十进制:

结果如下所示:

0.3000000000000000444089209850062616169452667236328125

由于精度问题,只取到0.30000000000000004。

答案

0.1+0.2 不等于 0.3 ,因为在 0.1+0.2 的计算过程中发生了两次精度丢失。第一次是在 0.1 和 0.2 转成双精度二进制浮点数时,由于二进制浮点数的小数位只能存储52位,导致小数点后第53位的数要进行为1则进1为0则舍去的操作,从而造成一次精度丢失。第二次在 0.1 和 0.2 转成二进制浮点数后,二进制浮点数相加的过程中,小数位相加导致小数位多出了一位,又要让第53位的数进行为1则进1为0则舍去的操作,又造成一次精度丢失。最终导致 0.1+0.2 不等于0.3 。

拓展

若你回答出来,面试官还可能继续问你:“ 0.1+0.2 不等于 0.3 会引起那些BUG?”

可以这样回答:“ 会引起统计页面展示错乱的BUG,还有 300.01 优惠300 元后,支付金额不足0.01 元等类似的BUG。”

还可能继续问道:“怎么解决 0.1+0.2 不等于 0.3 这个问题”。

可以这样回答:“可以用Math.js数学计算库来解决,或者用toFixed()给计算结果四舍五入,但是toFixed()在chrome或者火狐浏览器下四舍五入也有精度误差。可以用Math.round来解决精度误差,比如要把 2.55 四舍五入保留 1 位小数,先把 2.55∗10 得到 25.5 ,再用Math.round取整25.5 ,会得到25,再把 25÷10 得到 2.5 ,就这样间接实现了四舍五入。可以用Math.pow来做个简单的封装Math.round(Math.pow(10, m) * number) / Math.pow(10, m),其中number是要四舍五入的数,m是保留几位小数。

关注微信公众号:互联网架构师,在后台回复:2T,可以获取我整理的教程,都是干货。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别

9、2T架构师学习资料干货分享

非科班前端人的一道送命题:0.1+0.2 等于 0.3 吗?相关推荐

  1. 听说「面向对象是怎样工作的?」是一道送命题?| 7月书讯

    简报: 本月图灵计划出品14本图书,包含了6本IT技术图书.2本哈代的数学巨作.3本数学科普书.2本设计类图书.1本职场技能类图书.看看你最期待哪本书?别忘参与文末留言活动哦! 如果你是程序员,那么有 ...

  2. 【面试招聘】非科班的秋招攻略贴

    秋招进程过半,最近很多人看到我的面经的帖子都在询问楼主做什么的,非科班该如何备战秋招,因为实在一个个的回复起来比较麻烦,这里趁着闲暇时光整理了一下自己作为一个非科班的学生是如何准备秋招的过程,供大家参 ...

  3. web前端能拿多少钱?非科班的能转到web前端吗?

    有人说,现在前端都饱合了,找不到工作. 那是他水平不行,是他找不到工作.去拉钩,智联看看,大把的高薪职位.问题是他拿不到. 要项目没项目,好吧,有时候学历也能唬人,但是学历也不行的,指望面试官是个渣渣 ...

  4. 一道CF送命题引发的博文

    今天想把这道藏了1年的题写完,就顺便把相关算法看了一下. 包括3部分代码:LIS O(n^2)的写法 LIS O(nlogn)的写法送命题:codeforces714E 代码 叫送命题是因为这是去年打 ...

  5. 4年前端、2年CTO:一个非科班程序员的真实奋斗史

    1.引言 我,Scott,一家创业公司的 CTO. 从业6年却很少写文章,近一年来接触了几十个刚毕业的前端新人,也面试了100多个前端工程师和Nodejs工程师,对于前端发展的这个职业算是有些感触吧, ...

  6. 与人斗其乐无穷,教你回答职场送命题!

    职场如战场,人心深似海.没点求生欲,还真没办法在职场好好活下去.跟老板说话要小心翼翼,跟同事说话要谨慎三四,跟客户说话要客客气气,就连跟扫地阿姨说话都要轻声轻气.有时候对方的话里带话,稍微一走神,顿时 ...

  7. 保持生长不焦虑,非科班程序媛的进击

    我们为什么叫「递归」 "递归" (recursion) 是一种在程序设计语言中被广泛使用的算法.它有两大特点,一是调用自己,二是化繁为简.我们当中那些优秀的技术人又何尝不是如此?他 ...

  8. 计算机科班与非科班学编程有什么差距?

    先说观点:在没学计算机专业之前,大家都是零基础. 计算机专业科班出身学编程确实有优势,但是这并不意味着非计算机专业就一定比科班出身的差,技术都是不断更新迭代的,能坚持学到最后的才是真正具有专业精神的人 ...

  9. 非科班程序员与科班程序员的区别在哪里?

    [文章来源微信公众号:每天学编程] 作为一名典型的非科班程序员,我在学习和工作一段时间之后,发现了自己跟科班程序员还是有很多的的区别,不管是思维上还是做事风格,以及对待问题的解决方式,都感觉有些差强人 ...

  10. 【Java面经】非科班渣硕转行及求职分享

    背景介绍 楼主某末流985渣硕一枚,磕盐不会,偶然接触了下编程,然后又稍微学了学Java,后面就走上了程序猿的道路,今年四月侥幸去菊厂实习了一波(虽然没学到东西). 秋招拿了几个一般的offer(大佬 ...

最新文章

  1. byte endian(biglittle endian)
  2. 关于owner group others的测试
  3. Solr搜索引擎 — 通过mysql配置数据源
  4. synchronsized修饰方法的使用
  5. Git更新到最新版本
  6. 人工神经网络_用人工神经网络控制猴子大脑,MIT科学家做到了
  7. kux格式怎么转换成mp3_把MP3格式的音频转换成WAV格式
  8. python echo(msg) 字符串_[宜配屋]听图阁
  9. html标签强制转换位置,王老师html零基础学习笔记第4课——样式初始化+类型转化...
  10. 为什么说Serverless是云的未来?
  11. ROSE User Case View
  12. 学习C++项目——数据库知识学习(主从原理,分离配置,远程工具只是了解,都没有实现)
  13. 服务器关机显示正在停止服务,云服务器一直停止中
  14. nj04---事件回调函数
  15. linux安装weblogic界面,Weblogic11g 安装Linux下无Weblogic安装图形界面
  16. Word VBA-标题设置
  17. OpenGL 渐变色背景
  18. edgewin10无法安装_处理win10无法打开edge怎么解决
  19. TI四芯片级联雷达评估板-校准
  20. EmguCV学习(三)

热门文章

  1. 如何用EasyRecovery找回删除的文档(附注册机下载地址)
  2. 作为一个职业达人,你需要水滴石出的专注
  3. [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.17
  4. win7下安装cygwin工具
  5. git stash 和还原某个文件版本
  6. 【经典算法】第一回:快速排序
  7. Oracle 角色权限表
  8. 「leetcode」C++题解:239. 滑动窗口最大值,单调队列的经典题目
  9. Wolfram Mathematica 13 for Mac(功能广泛的科学计算软件)中文版
  10. Rhino 7 for Mac(犀牛3D造型软件)