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 相关文章推荐
小议Function.apply() 之一------(函数的劫持与对象的复制)
Nov 30 Javascript
for 循环性能比较 提高for循环的效率
Mar 19 Javascript
js获取图片长和宽度的代码
Nov 24 Javascript
js原生appendChild的bug解决心得分享
Jul 01 Javascript
node.js中的fs.fchown方法使用说明
Dec 16 Javascript
JS 实现可停顿的垂直滚动实例代码
Nov 23 Javascript
详谈JavaScript的闭包及应用
Jan 17 Javascript
JS实现简单短信验证码界面
Aug 07 Javascript
js基于FileSaver.js 浏览器导出Excel文件的示例
Aug 15 Javascript
JS验证码实现代码
Sep 14 Javascript
重学JS之显示强制类型转换详解
Jun 30 Javascript
vue如何使用async、await实现同步请求
Dec 09 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
php二维数组排序详解
2013/11/06 PHP
php解析字符串里所有URL地址的方法
2015/04/03 PHP
PHP对象的浅复制与深复制的实例详解
2017/10/26 PHP
PHP的微信支付接口使用方法讲解
2019/03/08 PHP
解决使用attachEvent函数时,this指向被绑定的元素的问题的方法
2007/08/13 Javascript
javascript 语法基础 想学习js的朋友可以看看
2009/12/16 Javascript
mysql输出数据赋给js变量报unterminated string literal错误原因
2010/05/22 Javascript
uploadify在Firefox下丢失session问题的解决方法
2013/08/07 Javascript
自定义jQuery插件方式实现强制对象重绘的方法
2015/03/23 Javascript
JavaScript编程中实现对象封装特性的实例讲解
2016/06/24 Javascript
关于input全选反选恶心的异常情况
2016/07/24 Javascript
JSON键值对序列化和反序列化解析
2017/01/24 Javascript
JS实现的简单表单验证功能完整实例
2017/10/14 Javascript
AngularJS实现的简单拖拽功能示例
2018/01/02 Javascript
纯JS实现可用于页码更换的飞页特效示例
2018/05/21 Javascript
TypeScript中使用getElementXXX()的示例代码
2019/09/12 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
2019/09/17 Javascript
JavaScript RegExp 对象用法详解
2019/09/24 Javascript
Python 常用string函数详解
2016/05/30 Python
Python3利用SMTP协议发送E-mail电子邮件的方法
2017/09/30 Python
详解python3中的真值测试
2018/08/13 Python
Django的models中on_delete参数详解
2019/07/16 Python
django中上传图片分页三级联动效果的实现代码
2019/08/30 Python
Python实现变声器功能(萝莉音御姐音)
2019/12/05 Python
python opencv根据颜色进行目标检测的方法示例
2020/01/15 Python
利用django model save方法对未更改的字段依然进行了保存
2020/03/28 Python
keras分类模型中的输入数据与标签的维度实例
2020/07/03 Python
HTML5 embed标签定义和用法详解
2014/05/09 HTML / CSS
用HTML5制作一个简单的桌球游戏的教程
2015/05/12 HTML / CSS
Under Armour安德玛法国官网:美国高端运动科技品牌
2018/06/29 全球购物
消防安全月活动总结
2015/05/08 职场文书
革命电影观后感
2015/06/18 职场文书
经销商会议开幕词
2016/03/04 职场文书
学生会2016感恩节活动小结
2016/04/01 职场文书
再也不用花钱买漫画!Python爬取某漫画的脚本及源码
2021/06/09 Python
python中redis包操作数据库的教程
2022/04/19 Python