js为什么不能正确处理小数运算?


Posted in Javascript onDecember 29, 2015
var sum = 0;
for(var i = 0; i < 10; i++) {
 sum += 0.1;
}

console.log(sum);

上面的程序会输出1吗?

你有必要知道的 25 个 JavaScript 面试题 一文中,第 8 个题浅显的说了下 js 为什么不能正确处理小数运算的问题。今天重拾旧题,更深层次的剖析下这个问题。

但要先说明的是,不能正确处理小数的运算并不是 JavaScript 语言本身的设计错误,其它高级编程语言,如C,Java等,也是不能正确处理小数运算的:

#include <stdio.h>

void main(){
  float sum;
  int i;
  
  sum = 0;
  
  for(i = 0; i < 100; i++) {
    sum += 0.1;
  }
  
  printf('%f\n', sum); //10.000002
}

数在计算机内部的表示

我们都知道,用高级编程语言编写的程序需要经过解释、编译等操作转变成 CPU(Central Processing Unit) 可以识别的机器语言才能运行,而对 CPU 来说,它不识别数的十进制、八进制和十六进制等,我们在程序中声明的这些进制数都会被转成二进制数进行运算。

为什么不是转换成三进制数进行运算呢?

计算机内部是由很多的 IC (Integrated Circuit: 集成电路) 这种电子部件构成的,它的长相大概是这样子:

js为什么不能正确处理小数运算?

IC 有很多种形状,在其两侧或内部并排排列着很多引脚(图示只画出了一侧)。IC 的所有引脚,只有直流电压 0V 或 5V 两个状态,即一个 IC 引脚只能表示两个状态。IC 的这个特性就决定了计算机内部的数据只能用二进制数处理。

由于1 位(一个引脚)只能表示两个状态,所以二进制的计算方式就变成了 0、1、10、11、100….这种形式:

js为什么不能正确处理小数运算?

所以,在数的运算中,所有操作数都会被转成二进制数参与运算,如39,会被转换成二进制 00100111

小数的二进制表示

如前文所说,程序中的数据都会被转换成二进制数,小数参与运算时,也会被转成二进制,如十进制的11.1875 会被转换成1101.0010。

小数点后 4 位用二进制数表示的数值范围是 0.0000~0.1111,因此,这只能表示 0.5、0.25、0.125、0.0625 这四个十进制数以及小数点后面的位权组合(相加)而成的小数:

js为什么不能正确处理小数运算?

从上表可以看出,十进制数 0 的下一位是 0.0625,所以,0~0.0625 之间的小数,就无法用小数点后 4 位数的二进制数表示;如果增加二进制数小数点后面的位数,与其相对应的十进制数的个数也会增加,但无论增加多少位,都无法得到 0.1 这个结果。实际上,0.1 转换成二进制是 0.00110011001100110011…… 注意 0011 是无限重复的:

console.log(0.2+0.1);

//操作数的二进制表示
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)

js 的 Number 类型并没有像 C / Java 等分整型、单精度、双精度等,而是统一表现为双精度浮点型。按照 IEEE 的规定,单精度浮点数用 32 位表示全体小数,而双精度浮点数用 64 位表示全体小数,而浮点数由符号、尾数、指数和基数组成,所以并不是所有的位数都用来表示小数,符号、指数等也要占据位数,基数不占据位数:

js为什么不能正确处理小数运算?

双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100…因浮点数小数位的限制而截断的二进制数字,这时候,再把它转换为十进制,就成了 0.30000000000000004。

总结

js 不能正确处理小数运算,包括其它高级编程语言一样,这不是语言本身的设计错误,而是计算机内部本身就不能正确处理小数的运算,对小数的运算往往会得到意想不到的结果,因为并不是所有的十进制小数能被二进制表示。

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
JQueryEasyUI datagrid框架的进阶使用
Apr 08 Javascript
JavaScript实现动态添加,删除行的方法实例详解
Jul 02 Javascript
JavaScript简单修改窗口大小的方法
Aug 03 Javascript
浅谈Javascript中substr和substring的区别
Sep 30 Javascript
javascript仿京东导航左侧分类导航下拉菜单效果
Nov 25 Javascript
express文件上传中间件Multer详解
Oct 24 Javascript
JS验证字符串功能
Feb 22 Javascript
jQuery插件echarts实现的去掉X轴、Y轴和网格线效果示例【附demo源码下载】
Mar 04 Javascript
vue中各组件之间传递数据的方法示例
Jul 27 Javascript
axios携带cookie配置详解(axios+koa)
Dec 28 Javascript
Node.js API详解之 dns模块用法实例分析
May 15 Javascript
浅谈JavaScript浅拷贝和深拷贝
Nov 07 Javascript
javascript从作用域链谈闭包
Jul 29 #Javascript
你有必要知道的25个JavaScript面试题
Dec 29 #Javascript
JavaScript仿支付宝密码输入框
Dec 29 #Javascript
js实现商城星星评分的效果
Dec 29 #Javascript
原生js配合cookie制作保存路径的拖拽
Dec 29 #Javascript
一种新的javascript对象创建方式Object.create()
Dec 28 #Javascript
JavaScrip常见的一些算法总结
Dec 28 #Javascript
You might like
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
php解决约瑟夫环算法实例分析
2019/09/30 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
Dojo Javascript 编程规范 规范自己的JavaScript书写
2014/10/26 Javascript
Thinkphp模板没有解析直接原样输出的解决方法
2014/10/31 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
2015/03/30 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
2017/03/27 Javascript
webpack+vue中使用别名路径引用静态图片地址
2017/11/20 Javascript
详解vue移动端日期选择组件
2018/02/22 Javascript
Vue项目部署在Spring Boot出现页面空白问题的解决方案
2018/11/26 Javascript
详解JS判断页面是在手机端还是在PC端打开的方法
2019/04/26 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
layer.open 子页面弹出层向父页面传输数据的例子
2019/09/26 Javascript
JS中循环遍历数组的四种方式总结
2021/01/23 Javascript
js实现简单商品筛选功能
2021/02/02 Javascript
[50:11]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第三场
2018/04/09 DOTA
python获取元素在数组中索引号的方法
2015/07/15 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
详解Python最长公共子串和最长公共子序列的实现
2018/07/07 Python
Linux系统(CentOS)下python2.7.10安装
2018/09/26 Python
Python多进程方式抓取基金网站内容的方法分析
2019/06/03 Python
Python实现微信机器人的方法
2019/09/06 Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
2020/05/15 Python
深入浅析pycharm中 Make available to all projects的含义
2020/09/15 Python
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
Falconeri美国官网:由羊绒和羊毛制成的针织服装
2018/04/08 全球购物
小班重阳节活动方案
2014/02/08 职场文书
机关党员2014全国两会学习心得体会
2014/03/10 职场文书
手机银行营销方案
2014/03/14 职场文书
2014基建处领导班子“四风”对照检查材料思想汇报
2014/10/04 职场文书
2014年标准化工作总结
2014/12/17 职场文书
主婚人致辞精选
2015/07/28 职场文书
Pytest实现setup和teardown的详细使用详解
2021/04/17 Python
app场景下uniapp的扫码记录
2022/07/23 Java/Android
volatile保证可见性及重排序方法
2022/08/05 Java/Android