文章目录

  • 0.1+0.2 等于 0.3 吗?
    • 0.1+0.2 的计算过程。
    • 转成浮点数
    • 浮点数相加
    • 浮点数转成十进制
      • 结果如下所示:
    • 答案
    • 拓展
    • 解决方式

点击打开视频讲解

0.1+0.2 等于 0.3 吗?

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

0.1+0.2 的计算过程。

1、十进制转成二进制
在JS内部所有的计算都是以二进制方式计算的。 所以运算 0.1+ 0.2 时要先把 0.1和 0.2 从十进制转成二进制。
0.1转化成二进制的算法:0.1*2=0.2======取出整数部分00.2*2=0.4======取出整数部分00.4*2=0.8======取出整数部分00.8*2=1.6======取出整数部分10.6*2=1.2======取出整数部分1接下来会无限循环0.2*2=0.4======取出整数部分00.4*2=0.8======取出整数部分00.8*2=1.6======取出整数部分10.6*2=1.2======取出整数部分1
所以0.1转化成二进制是:0.0001 1001 1001 1001......0.2转化成二进制的算法:0.2*2=0.4======取出整数部分00.4*2=0.8======取出整数部分00.8*2=1.6======取出整数部分10.6*2=1.2======取出整数部分1接下来会无限循环0.2*2=0.4======取出整数部分00.4*2=0.8======取出整数部分00.8*2=1.6======取出整数部分10.6*2=1.2======取出整数部分1
所以0.2转化成二进制是:0.0011 0011 0011 0011......

这里要注意 0.1 和 0.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,如下所示:

 101100110011001100110011001100110011001100110011001111011001100110011001100110011001100110011001100110100

截掉小数位的最后一位相当把小数点向左移了一位,故指数位要加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来解决精度误差,四舍五入。可以用Math.pow来做个简单的封装Math.round(Math.pow(10, m) * number) / Math.pow(10, m),其中number是要四舍五入的数,m是保留几位小数。

若对您有帮助,请点击跳转到B站一键三连哦!感谢支持!!!

0.1+0.2 等于 0.3 吗?(数字相加结果有无限小数的原因及解决方式)相关推荐

  1. verilog 浮点转定点_浮点数0.1+0.2为何不等于0.3

    来自公众号:印记中文 本文由扇贝的前端工程师景国凯撰写,跟随作者一起了解浮点数的计算过程,掌握为何会出现精度丢失的根本原因. 之前简单介绍了二进制下整数的加减乘除基本运算,建议没看过的先去了解一下,这 ...

  2. input 0.1无法相加_你真的知道0.1+0.2为何不等于0.3吗?

    打开chrome控制台,给一个特别简单的输入如下: 0.1 + 0.2 // 0.30000000000000004 复制代码 不知道你有没有吃惊,这么简单的一个计算,无论在js中还是在python中 ...

  3. 0.1+0.2真不等于0.3?你知道不

    先看下代码: <script>console.log(0.1+0.2) </script> 打印出来的值 有什么办法解决呢? bignumber.js 1.引入到项目中: &l ...

  4. 当x大于时,y等于1;当x等于0时,y等于0;当x小于0时,y等于-1。

    #include<stdio.h> int main() {int x,y;scanf("%d",&x);if(x > 0)y = 1;else if(x ...

  5. JS 0.1+0.2为什么不等于0.3

    出现现象 0.1 + 0.2 === 0.3; // false 为什么会这样? 简单地说,number在内存中是以64位二进制存储的,所以0.1 和 0.2 的二进制表示形式是不精确的,所以它们相加 ...

  6. python0.1+0.2不等于0.3_为什么0.1 + 0.2不等于0.3?

    原标题:为什么0.1 + 0.2不等于0.3? 0.1 + 0.2不等于0.3这是一个普遍的问题,例如在JS控制台输入将得到0.30000000000000004 在python的控制台也是输出这个数 ...

  7. 实数系的基本定理_初中篇1|知实数-为什么0.9的循环等于1?

    (初一下学期)弘毅: 为什么0.9的循环等于1? 我:说来话长,你坐下听我慢慢说. 摘要:1. 该问题的普遍性2. 有理数3. 从有理数到实数4. 真正理解实数-极限与拓扑5. 关于高中及以前的数学- ...

  8. 如何解决JavaScript中0.1+0.2不等于0.3

    原文转载自:https://www.cnblogs.com/weshare/archive/2018/02/20/8455470.html >console.log(0.1+0.2===0.3) ...

  9. 解决JS中0.1+0.2不等于0.3

    console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个逻辑是正确的,但是在JavaScript中0.1+0.2!= ...

  10. 算法-----三数之和等于0

    三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件 且不重复的三元组. 注意:答案中不可以包含重 ...

最新文章

  1. 【hdu】4521 小明序列【LIS变种】【间隔至少为d】
  2. SQL 2014 in-memory中的storage部分
  3. 动态库、静态库、运行时库、引入库之间的区别
  4. Spring Cloud 系列之 Nacos 配置中心
  5. 创业者谈:畏惧失败,但也要拥抱失败
  6. 用scikit-learn学习主成分分析(PCA)
  7. php 的html文件怎么打开,什么是html文件?html格式如何打开?(图)
  8. html label 两端对齐,如果实现表单的label文字两端对齐
  9. Linux Redis安装及使用
  10. 364 页 PyTorch 版《动手学深度学习》分享(全中文,支持 Jupyter 运行)
  11. 计算机大学毕业好考公务员,哪些大学的毕业生更容易考上公务员?
  12. linux java keytool_JDK自带的keytool证书工具详解
  13. 软件工程毕业论文mysql英文翻译_软件工程毕业论文文献翻译中英文对照
  14. 计算机桌面图标变小了,电脑桌面图标变小了怎么办
  15. 远程桌面控制计算机,如何远程控制电脑?远程控制别人计算机(2种实用方法)...
  16. Window系列 (一) — WindowManager 详解
  17. 写给立志进入网络行业的朋友的一些忠告
  18. n维立方体角、面、边的个数
  19. C#入门学习——飞行棋
  20. 迅为-iMX6ULL开发板上配置AP热点

热门文章

  1. csu1164 Dominating
  2. UVa 12304 2D Geometry 110 in 1!(圆的处理)
  3. 【原创】《矩阵的史诗级玩法》连载十七:用矩阵研究二次贝塞尔曲线和抛物线的关系(上)
  4. 计步器 c语言,ADXL345单片机计步器程序
  5. 面向对象:上得厅堂,下得厨房,站起来杀猪,坐下来写书
  6. vue alert内含有html,vue一步步实现alert功能
  7. 路由器:什么是软路由,看完本篇文章你就懂了
  8. android wifi分析 实现原理,android framework wifi 开启原理
  9. Git报错Kex_exchange_identification
  10. 论文阅读 之 Person Re-identification in the Wild