在 js 中进行数学的运算时,会出现0.1+0.2=0.300000000000000004的结果,一开始认为是浮点数的二进制存储导致的精度问题,但这似乎不能很好的解释为什么在同样的存储方式下0.3+0.4=0.7可以得到正确的结果。本文主要通过浮点数的二进制存储及运算,和IEEE754下的舍入规则,解释为何会出现这种情况。

一、浮点数的二进制存储

JavaScript遵循IEEE754标准,在64位中存储一个数据的有效数字形式。

其中,第0位为符号位,0表示正数1表示负数;第1到11位存储指数部分;第12到63位存小数部分(尾数部分)(即有效数字)。由于二进制的有效数字总是表示为 1.xxx…的形式,尾数部分在规约形式下的第一位默认为1,故存储时第一位省略不写,尾数部分f存储有效数字小数点后的xxx...,最长52位。因此,JavaScript提供的有效数字最长为53个二进制位(尾数部分52位+被省略的1位)。

以0.1、0.2、0.3、0.4和0.7的二进制形式为例:

0.1->0.0001100110011...(0011无限循环)->0-01111111011-(1 .)1001100110011001100110011001100110011001100110011010(入)0.2->0.001100110011...(0011无限循环)->0-01111111100-(1 .)1001100110011001100110011001100110011001100110011010(入)0.3->0.01001100110011...(0011无限循环)->0-01111111101-(1 .)0011001100110011001100110011001100110011001100110011(舍)0.4->0.01100110011...(0011无限循环)->0-01111111101-(1 .)1001100110011001100110011001100110011001100110011010(入)0.7->0.101100110011...(0011无限循环)->0-01111111110-(1 .)0110011001100110011001100110011001100110011001100110(舍)

对于52位之后进行舍入运算,此时可看作0舍1入(具体舍入规则在第三部分详细说明),有精度损失。

二、对阶运算

由于指数位数不同,运算时需要进行对阶运算。对阶过程略,0.1+0.2与0.3+0.4的尾数求和结果分别如下:

0.1+0.2->10.01100110011001100110011001100110011001100110011001110.3+0.4->10.1100110011001100110011001100110011001100110011001101

求和结果需规格化(有效数字表示),右规导致低位丢失,此时需对丢失的低位进行舍入操作:

0.1+0.2->1.00110011001100110011001100110011001100110011001100111->1.0011001100110011001100110011001100110011001100110100(入)0.3+0.4->1.01100110011001100110011001100110011001100110011001101->1.0110011001100110011001100110011001100110011001100110(舍)

即:
00111->0100
01101->0110

此处同样有精度损失。在这里我们可以发现,0.3+0.4对阶阶运算且规格化后的运算结果与0.7在二进制中的存储尾数相同(可对照尾数后几位),而0.1+0.2的运算结果与0.3的存储尾数不同,且0.1+0.2转化为十进制时结果为0.300000000000000004。
此时,虽然0.1+0.2与0.3+0.4进行舍入操作的近似位都为1,但一入一舍导致计算结果与“标准答案”的异同。

三、IEEE754标准下的舍入规则

维基百科对最近偶数舍入原则的解释如下:舍入到最接近,在一样接近的情况下偶数优先(Ties To Even,这是默认的舍入方式),即会将结果舍入为最接近(精度损失最小)且可以表示的值,但是当存在两个数一样接近的时候,则取其中的偶数(在二进制中是以0结尾的)。

首先要注意的是,保留小数不是只看后面一位或者两位,而是看保留位后面的所有位。

如图,可以看到近似需要看三位,保留位(近似后的最低位)、近似位(保留位的后一位)、粘滞位(sticky bit 近似位后的所有位进行或运算后看作一位)。
当粘滞位为1时,舍入规则可以看作0舍1入,近似位为0舍,近似位为1入(即第一部分小数二进制存储为52位尾数时所进行的舍入操作)。
当粘滞位为0时,若近似位为0则舍去。
当粘滞位为0时,若近似位为1,无论舍入精度损失都相同,故需取舍入两种结果中的偶数:保留位为1时入,保留位为0时舍(即第二部分对阶运算规格化时的舍入操作)。

四、总结思考

由于IEEE754标准,这样的“bug”不止在JavaScript中会出现,在所有采用该标准的语言中都会存在,实际编程中可以通过设置精度保留位数等方式解决。

想了解跟多的基础理念指南:

1、关注我,转发+评论

2、私信发送:【电子书】,即可领取

lua 从一串数字中取出偶数位的数字_为什么JavaScript中 0.1 0.2 不等于0.3?相关推荐

  1. CF628D Magic Numbers (数据大+数位dp)求[a,b]中,偶数位的数字都是d,其余为数字都不是d,且能被m整除的数的个数...

    题意:求[a,b]中,偶数位的数字都是d,其余为数字都不是d,且能被m整除的数的个数(这里的偶数位是的是从高位往低位数的偶数位).a,b<10^2000,m≤2000,0≤d≤9 a,b< ...

  2. 【LeetCode】剑指 Offer 44. 数字序列中某一位的数字

    [LeetCode]剑指 Offer 44. 数字序列中某一位的数字 文章目录 [LeetCode]剑指 Offer 44. 数字序列中某一位的数字 package offer;public clas ...

  3. leetcode-剑指 Offer 44. 数字序列中某一位的数字

    记录需要找数字规律的题: 数字以0123456789101112131415-的格式序列化到一个字符序列中.在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等.请写一个函数 ...

  4. 【LeetCode笔记】剑指 Offer 44. 数字序列中某一位的数字(Java、偏数学)

    文章目录 题目描述 思路 && 代码 题目描述 比较偏数学的一道题..众所周知这类题代码量都不大,但是就是难想= = 思路 && 代码 这篇题解写得很好- 建议还是直接 ...

  5. 找出列表中的偶数位元素

    0 引言 运用函数截取列表中元素. 1 问题 找出一个列表中的偶数. 2 方法 定义一个函数,套用条件语句,将能够被2整除的偶数位元素放入一个新的列表中,打印这个列表. 3 实验结果与讨论 通过实验. ...

  6. 得到一个数字中每一位的数字

    学习编程也有一段时间了,随着学习的不断深入,我越来越体会到了算法的重要性,最近遇到了一些非常有意思的算法,比如打印水仙花数.将数字逆置,在这两个算法中会用到一个数字钟每一位的值 如:判断数字123是否 ...

  7. (每天一小步,进步一大步)NC291 数字序列中某一位的数字

    数字以 0123456789101112131415... 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输 ...

  8. mysql中以下正确的sql是_总结MySQL中SQL语法的使用

    --where子句操作符: where子句操作符 = 等于 <> 不等于(标准语法) != 不等于(非标准语法,可移植性差) < 小于 <= 小于等于 > 大于 > ...

  9. python下列数据中不属于字符串的是_下列数据中,不属于字符串的是( )。_学小易找答案...

    [单选题]字符串的strip方法的作用是( ). [其它]请根据下述需求,编写一个程序: 用户输入一个字符串,将下标为偶数的字符串提出来合并成一个新的字符串A,再将下标为奇数的字符串提出来合并成一个新 ...

最新文章

  1. eclipse中使用maven创建项目JDK版本默认是1.5解决方法
  2. java创建线程的2种方式
  3. React + TypeScript:元素引用的传递
  4. XCode 编辑器的shortcuts
  5. SpringBoot四大核心组件,你了解多少
  6. 计算机右键管理快捷键,鼠标右键菜单管理
  7. XML 转 JSON
  8. Geometric application of BSTs
  9. java fifo lifo_栈方法 LIFO - 队方法 FIFO
  10. 最小二乘法拟合二次曲线 C语言
  11. 《2023新一代数字办公白皮书》正式发布!| 爱分析报告
  12. centos7.9编译安装构建系统gn+ninja
  13. 微信iOS新版支持手机、iPad、电脑同时在线
  14. TwinCAT3 ADS通讯笔记
  15. 项目经验教训总结(教育软件)
  16. GNS3-GREvpn
  17. 分享个热血三国辅助脚本,教你热血三国手游多开
  18. cad2016中选择全图字体怎么操作_高大上PPT的四个关键词:极简、全图、创意、潮流...
  19. 第一章 强化学习介绍
  20. windows show failed无法启动你的相机

热门文章

  1. P3865 【模板】ST表
  2. Kylin工作原理、体系架构
  3. php中__autoload()方法详解
  4. C# 判断给定大数是否为质数,目标以快速度得到正确的计算结果。
  5. Interview and paper based test
  6. 关于活动对像要注意的问题
  7. 迷你飞信一出,LibFetion该挂了把
  8. VScode 结局插件prettier和vetur格式化冲突
  9. JavaScrpt --- es5实现ES6的Number扩展(部分)
  10. eoLinker-API_Shop_验证码识别与生成类API调用的代码示例合集:六位图片验证码生成、四位图片验证码生成、简单验证码识别等...