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 相关文章推荐
javascript 动态数据下的锚点错位问题解决方法
Dec 24 Javascript
JavaScript Chart 插件整理
Jun 18 Javascript
一个可绑定数据源的jQuery数据表格插件
Jul 17 Javascript
js弹出层之1:JQuery.Boxy (二)
Oct 06 Javascript
兼容最新firefox、chrome和IE的javascript图片预览实现代码
Aug 08 Javascript
js实现文件上传表单域美化特效
Nov 02 Javascript
原生js封装的一些jquery方法(详解)
Sep 20 Javascript
用jmSlip编写移动端顶部日历选择控件
Oct 24 Javascript
zTree jQuery 树插件的使用(实例讲解)
Sep 25 jQuery
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
Jul 26 Javascript
vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)
Sep 05 Javascript
extjs图形绘制之饼图实现方法分析
Mar 06 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时间不正确的解决方法
2008/04/09 PHP
PHP读取XML值的代码(推荐)
2011/01/01 PHP
web server使用php生成web页面的三种方法总结
2013/10/28 PHP
ThinkPHP和UCenter接口冲突的解决方法
2016/07/25 PHP
yii2.0整合阿里云oss的示例代码
2017/09/19 PHP
laravel框架中间件简单使用方法示例
2020/01/25 PHP
在Javascript中定义对象类别
2006/12/22 Javascript
ie 处理 gif动画 的onload 事件的一个 bug
2007/04/12 Javascript
javascript 从if else 到 switch case 再到抽象
2010/07/17 Javascript
基于jquery的滑动样例代码
2010/11/20 Javascript
纯JS实现的批量图片预览加载功能
2011/08/14 Javascript
jQuery操作cookie方法实例教程
2014/11/25 Javascript
jQuery实现首页图片淡入淡出效果的方法
2015/06/10 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
超实用的JavaScript代码段 附使用方法
2016/05/22 Javascript
浅谈如何实现easyui的datebox格式化
2016/06/12 Javascript
JS图片定时翻滚效果实现方法
2016/06/21 Javascript
AngularJS 指令详细介绍
2016/07/27 Javascript
jQuery制作input提示内容(兼容IE8以上)
2017/07/05 jQuery
微信小程序文章详情页面实现代码
2018/09/10 Javascript
vue-cli 3.x 修改dist路径的方法
2018/09/19 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
vue项目中监听手机物理返回键的实现
2020/01/18 Javascript
javascript 函数的暂停和恢复实例详解
2020/04/25 Javascript
JavaScript array常用方法代码实例详解
2020/09/02 Javascript
Python随机生成数模块random使用实例
2015/04/13 Python
在Python中操作时间之tzset()方法的使用教程
2015/05/22 Python
go和python变量赋值遇到的一个问题
2017/08/31 Python
Python opencv实现人眼/人脸识别以及实时打码处理
2019/04/29 Python
python向字符串中添加元素的实例方法
2019/06/28 Python
python+numpy实现的基本矩阵操作示例
2019/07/19 Python
同学聚会欢迎辞
2014/01/14 职场文书
小时代观后感
2015/06/10 职场文书
素质拓展训练感想
2015/08/07 职场文书
小学英语教学随笔
2015/08/14 职场文书
SQL实战演练之网上商城数据库商品类别数据操作
2021/10/24 MySQL