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 相关文章推荐
js word表格动态添加代码
Jun 07 Javascript
js对数字的格式化使用说明
Jan 12 Javascript
再次分享18个非常棒的jQuery表格插件
Apr 10 Javascript
JavaScript使用push方法添加一个元素到数组末尾用法实例
Apr 06 Javascript
jquery插件orbit.js实现图片折叠轮换特效
Apr 14 Javascript
简单介绍JavaScript中字符串创建的基本方法
Jul 07 Javascript
jQuery实现的Div窗口震动效果实例
Aug 07 Javascript
详解JS正则replace的使用方法
Mar 06 Javascript
使用Ajax与服务器(JSON)通信实例
Nov 04 Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
May 29 Javascript
js中对象和面向对象与Json介绍
Jan 21 Javascript
swiper4实现移动端导航切换
Oct 16 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
搜索引擎技术核心揭密
2006/10/09 PHP
php4的彩蛋
2006/10/09 PHP
基于PHP创建Cookie数组的详解
2013/07/03 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
2014/09/24 PHP
ThinkPHP 404页面的设置方法
2015/01/14 PHP
浅谈php错误提示及查错方法
2015/07/14 PHP
实例讲解PHP验证邮箱是否合格
2019/01/28 PHP
javascript 用记忆函数快速计算递归函数
2010/03/15 Javascript
解决jquery的.animate()函数在IE6下的问题
2010/12/03 Javascript
javascript正则表达式中的replace方法详解
2015/04/20 Javascript
常用的Javascript设计模式小结
2015/12/09 Javascript
JS实现iframe编辑器光标位置插入内容的方法(兼容IE和Firefox)
2016/06/24 Javascript
jQuery实现简洁的轮播图效果实例
2016/09/07 Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
2017/02/21 Javascript
JavaScript限定范围拖拽及自定义滚动条应用(3)
2017/05/17 Javascript
详解Vue如何支持JSX语法
2017/11/10 Javascript
Angular4自制一个市县二级联动组件示例
2017/11/21 Javascript
jQuery实现checkbox全选功能完整实例
2018/07/12 jQuery
vue-router实现编程式导航的代码实例
2019/01/19 Javascript
仿vue-cli搭建属于自己的脚手架的方法步骤
2019/04/17 Javascript
laravel实现中文和英语互相切换的例子
2019/09/30 Javascript
详解Vue中的MVVM原理和实现方法
2020/07/15 Javascript
基于element-ui对话框el-dialog初始化的校验问题解决
2020/09/11 Javascript
解决element-ui的下拉框有值却无法选中的情况
2020/11/07 Javascript
python logging 日志的级别调整方式
2020/02/21 Python
浅谈SciPy中的optimize.minimize实现受限优化问题
2020/02/29 Python
快速解决jupyter notebook启动需要密码的问题
2020/04/21 Python
jupyter notebook oepncv 显示一张图像的实现
2020/04/24 Python
应届毕业生通用的自荐书范文
2014/02/07 职场文书
会议主持词
2014/03/17 职场文书
公司授权委托书范文
2014/09/21 职场文书
导游词幽默开场白
2019/06/26 职场文书
评估“风险”创业计划的几大要点
2019/08/12 职场文书
Python开发之QT解决无边框界面拖动卡屏问题(附带源码)
2021/05/27 Python
Mongo服务重启异常问题的处理方法
2021/07/01 MongoDB
pytest实现多进程与多线程运行超好用的插件
2022/07/15 Python