0.1+0.2 为什么不等于0.3

1 篇文章 0 订阅
订阅专栏
本文详细解析了0.1+0.2不等于0.3的原因,涉及二进制浮点数表示、精度丢失与计算过程。在JavaScript中,由于浮点数存储限制,导致计算0.1+0.2时产生精度误差,最终结果为0.30000000000000004。此外,还探讨了由此引发的编程误差及解决方案,如使用Math.js库或toFixed()方法。
摘要由CSDN通过智能技术生成

目录

一、0.1+0.2的计算过程

1.十进制转成二进制

2.转成浮点数

3.浮点数相加

4.浮点数转成十进制

二、答案

三、拓展


一、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...... 转成浮点数形式的二进制,转换结果如下图所示:

3.浮点数相加

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

为了行文方便,把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 ,那么相加后的浮点数如下所示:

4.浮点数转成十进制

二进制浮点数计算结束后,把结果(二进制的浮点数)转成十进制,其转换公式为

,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是保留几位小数。

为什么0.1+0.2不等于0.3
初夏0811的博客
02-09 2万+
首先来看一段诡异的代码: package org.sang.test; /** * @Author: chuxia0811 * @Date: 2021/2/9 22:55 * @Description : */ public class _01_02 { public static void main(String[] args) { float a = 0.1f; float b = 0.2f; System.out.println(a +
程序里为什么0.1+0.2不等于0.3
BeanInJ的博客
01-20 662
为什么0.1+0.2不等于0.30.1+0.2新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 0.1+0.2 程序里面0.1+0.2=0.30000000000000004 你好! 这是你第一次使用 Markdown编辑器
为什么 Python 中0.1 + 0.2 不等于 0.3
最新发布
pythondh1的博客
07-30 1017
print(is_close(0.1 + 0.2, 0.3)) # 输出:True。
0.1+0.2为什么不等于0.3
bug收集
06-02 641
面试时,经常会被问到 0.1+0.2 结果是多少呢? 知道结果,肯定不是0.3 请看下图: 可原因就不太清楚了,本文就来讨论下 原因: 在于在JS中采用的IEEE 754的双精度标准,计算机内部存储数据的编码的时候,0.1在计算机内部根本就不是精确的0.1,而是一个有舍入误差的0.1。 当代码被编译或解释后,0.1已经被四舍五入成一个与之很接近的计算机内部数字,以至于计算还没开始,一个很小的舍入错误就已经产生了。 这也...
为什么 0.1+0.2 不等于 0.3
weixin_42560424的博客
06-08 2813
位),而在这种格式下无法精确表示某些小数,因此在进行计算时会出现精度误差。中,这些小数会被转换成最接近它们的可表示值,然后再进行计算。被转换成的值可能会存在精度误差,导致它们的和不等于。都是无限循环小数,无法用二进制精确地表示。中采用的是双精度浮点数格式(
解决JavaScript0.1+0.2不等于0.3问题
10-17
这就是为什么在JavaScript中`0.1 + 0.2`不等于`0.3`的原因。 为了正确地比较两个浮点数,我们需要引入一个误差范围,也就是所谓的“机器精度”。在JavaScript中,这个精度值可以通过`Number.EPSILON`属性获取,其值...
为什么JavaScript0.1 + 0.2 != 0.3
01-21
涉及面试题:为什么 0.1 + 0.2 != 0.3?如何解决这个问题? 原因,因为 JS 采用 IEEE 754双精度版本(64位),并且只要采用 IEEE 754的语言都有该问题 我们都知道计算机是通过二进制来存储东西的,那么 0.1 在二进制...
js代码-面试题---0.1 +0.2 为啥不精确等于0.3
07-14
JavaScript中,0.1 + 0.2 不精确等于 0.3 是一个常见的面试问题,涉及到浮点数在计算机中的表示与计算。这个问题源于浮点数在二进制系统下的表示方式以及IEEE 754标准。下面将详细解释这一现象的原因以及相关的...
JavaScript0.1+0.2为什么不等于0.3?如何实现等于0.3?
越陌度阡
11-14 818
计算机中用二进制来存储小数,大部分小数转成二进制之后都是无限循环的值,因此存在取舍问题,也就是精度丢失。 如上所述:0.10.2在转换成二进制后会无限循环,由于标准位数的限制后面多余的位数会被截掉,此时就已经出现了精度的损失,相加后因浮点数小数位的限制而截断的二进制数字在转换为十进制就会变成 0.30000000000000004。 ......
[解惑][无用的知识] 为什么0.1+0.2不等于0.3
大宝剑
02-27 598
第一次遇到这个问题的时候我还是一个在培训班学习PHP的懵懂少年。我记得当时老师说的原因是"因为PHP在处理浮点数的时候有问题"。哎,PHP还是不是全世界最好的编程语言了。 后来无意发现,何止是PHP,C,Java,JavaScript等等等等都有这样的问题。看来PHP还是这个世界上最好的编程语言。 因为是无用的知识,所以先说结论:无关语言,之所以会出现这样的问题,是因为"有一些十进制小数无法转换成二进制数"。 下面详细说说这到底是为什么。 计算机如何用二进制表示小数 先来一张图说一下,如何把二进制小数101
【操作系统】为什么 0.1 + 0.2 不等于 0.3
flyersboy的博客
06-02 3387
一、为什么负数要用补码表示? 以 int 类型的数字作为例⼦,int 类型是 32 位的,其中最⾼位是作为「符号标志位」,正数的符号位是 0 ,负数的符号位是 1 ,剩余的 31 位则表示⼆进制数据。 那么,对于 int 类型的数字 1 的⼆进制数表示如下: ⽽负数就⽐较特殊了点,负数在计算机中是以「补码」表示的,所谓的补码就是把正数的⼆进制全部取反再加 1,⽐如 -1 的⼆进制是把数字 1 的⼆进制取反后再加 1,如下图: 那么,为什么计算机要⽤补码的⽅式来表示负数?**在回答这个问题前,我们假设不.
为什么 0.1 + 0.2 不等于0.3?如何解决这个问题?
weixin_47450807的博客
02-28 8194
一、开头 我们都知道0.1 + 0.2 !== 0.3,而是0.30000000000000004,那么是为什么?我们都知道计算机在内部实现中使用的是二进制,0.1也是不例外的,此时我们将0.1转换为二进制数据表示可以表示为:0.0001100110011001100...(1100无限循环),0.2转换为二进制数据可以表示为0.00110011001100...(1100循环),此时这两个数均为无限循环小数,那么该如何去存储呢? 二、如何存储二进制小数 不同的语言可能会有不同的存储标准,javascrip
0.1+0.2不等于0.3
高山景行,一尘不染
11-05 549
在正常的数学逻辑思维中,0.1+0.2=0.3这个逻辑是正确的,但是在JavaScript0.1+0.2!==0.3,在JavaScript中的二进制的浮点数0.10.2并不是十分精确,在他们相加的结果并非正好等于0.3,而是一个比较接近的数字 0.30000000000000004 ,所以条件判断结果为false。 原因很简单,因为0.1存储的值比实际值大了一点,0.2也是大了一点(差值比...
0.1 + 0.2 不等于 0.3
gsh1075035316的博客
08-10 183
>>> 0.1+0.2 0.30000000000000004 >>> >>> 0.1+0.2 == 0.3 False >>> round(0.1+0.2,1) == 0.3 True >>> 这个问题叫做 不确定尾数问题 不是只在python中存在 在很多编程语言中都存在 它涉及到了计算机对数字运算的内部实现原理 浮点数间运算存在不确定尾数,不是Bug 在计算机中所有数字都是由2进制表示 严格来说 53位二进
为什么 0.1 + 0.2 !== 0.3?如何解决这个问题?
mubo970901的博客
08-17 5744
众所周知,JavaScript在某些浮点数的运算时会出现精度丢失的问题,比如在控制台中输入0.1+0.2,得到的是0.30000000000000004,而不是精确的0.3,这是什么原因呢? 在计算机基础中我们应该学过,计算机中所有的数据最终都是以二进制的形式存储的,当然数字的存储也不例外。 当计算0.1+0.2的时候,实际上计算的是这两个数字在计算机里所存储的二进制,0.10.2 在转换为二进制表示的时候会出现位数无限循环的情况。当然计算机不会用无限的空间去存储这些无限循环的二进制数...
0.1+0.2等于0.3
07-27
在大多数编程语言中,0.1 + 0.2 不等于 0.3。这是由于浮点数在计算机中的表示方式导致的精度问题。 计算机使用二进制表示浮点数,而十进制中的 0.10.2 在二进制中是无限循环的小数。因此,在进行浮点数计算时,会存在一定的舍入误差。 如果我们在 Python 中执行 0.1 + 0.2 的计算,结果会接近 0.3,但并不完全等于 0.3。这是因为 Python 默认使用双精度浮点数(64位),它的精度是有限的。 下面是一个示例来说明这个问题: ```python result = 0.1 + 0.2 print(result) # 输出 0.30000000000000004 ``` 要在计算中处理精确的小数,可以使用 Decimal 类型。Decimal 类型提供了更高的精度,并可以避免浮点数运算中的舍入误差。 ```python from decimal import Decimal result = Decimal('0.1') + Decimal('0.2') print(result) # 输出 0.3 ``` 总之,当涉及浮点数计算时,我们应该意识到精度问题,并根据具体需求选择适当的解决方案。
写文章

热门文章

  • 0.1+0.2 为什么不等于0.3 12169
  • ABAP 数据库表读取输出 2769
  • ABAP 实战屏幕screen设计 2407
  • ABAP Tree Control的使用 2386
  • ABAP 标准列表和选择屏幕 2364

分类专栏

  • ABAP 8篇
  • web前端 1篇

最新评论

  • 0.1+0.2 为什么不等于0.3

    卡布奇诺www: Math.round四舍五入25.5 ,应该是会得到26,上面估计写忘记了

最新文章

  • ABAP 表控制TAKE CONTROL设计
  • ABAP Tree Control的使用
  • ABAP ALV控件的使用和ALV报表开发
2021年1篇
2019年9篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家西藏公园玻璃钢雕塑定制唐县玻璃钢铸铜雕塑6睢阳玻璃钢雕塑定制阳泉玻璃钢雕塑定制价格玻璃钢雕塑 慧聪网商场6周年庆美陈伊春玻璃钢卡通座椅雕塑宿州定做玻璃钢雕塑厂电话内蒙古户外景观玻璃钢雕塑菏泽佛像玻璃钢雕塑武汉佛像玻璃钢雕塑户外玻璃钢雕塑用什么材料威海人物玻璃钢雕塑安装玻璃钢动物牛雕塑厂家电话莱西玻璃钢花盆花器福州学校玻璃钢雕塑生产厂家陕西多彩玻璃钢雕塑销售电话广东节庆商场美陈供应旧玻璃钢花盆模具旧翻新视频新疆玻璃钢人物雕塑吉林步行街玻璃钢雕塑定做价格玻璃钢花盆潮州华安玻璃钢雕塑厂家淮安玻璃钢雕塑设计公司无锡玻璃钢仿铜雕塑厂家通化火烈鸟玻璃钢雕塑定制玻璃钢园林动物雕塑价格上海个性化玻璃钢雕塑哪家便宜重庆城市景观雕塑玻璃钢乐东黎族自治县玻璃钢雕塑厂家香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化