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 相关文章推荐
extjs render 用法介绍
Sep 11 Javascript
javascript去除字符串中所有标点符号和提取纯文本的正则
Jun 07 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
Dec 14 Javascript
JavaScript中用let语句声明作用域的用法讲解
May 20 Javascript
JavaScript常用判断写法大全(推荐)
May 30 Javascript
Boostrap基础教程之JavaScript插件篇
Sep 08 Javascript
微信小程序 页面传参实例详解
Nov 16 Javascript
为Jquery EasyUI 组件加上清除功能的方法(详解)
Apr 13 jQuery
让你彻底掌握es6 Promise的八段代码
Jul 26 Javascript
vue axios登录请求拦截器
Apr 02 Javascript
微信小程序本地存储实现每日签到、连续签到功能
Oct 09 Javascript
js前端图片加载异常兜底方案
Jun 21 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
改进的IP计数器
2006/10/09 PHP
phpmyadmin MySQL 加密配置方法
2009/07/05 PHP
php中var_export与var_dump的区别分析
2010/08/21 PHP
Yii核心组件AssetManager原理分析
2014/12/02 PHP
WordPress中is_singular()函数简介
2015/02/05 PHP
PHP中trim()函数简单使用指南
2015/04/16 PHP
PHP文件打开关闭及读写操作示例解析
2020/08/06 PHP
鼠标移动到一张图片时变为另一张图片
2006/12/05 Javascript
利用js 进行输入框自动匹配字符的小例子
2013/06/29 Javascript
javascript跟随滚动效果插件代码(javascript Follow Plugin)
2013/08/03 Javascript
Javascript基础知识(一)核心基础语法与事件模型
2014/09/29 Javascript
jQuery实现宽屏图片轮播实例教程
2015/11/24 Javascript
使用CDN和AJAX加速WordPress中jQuery的加载
2015/12/05 Javascript
jQuery焦点图插件SaySlide
2015/12/21 Javascript
Bootstrap基本组件学习笔记之导航(10)
2016/12/07 Javascript
div实现自适应高度的textarea实现angular双向绑定
2017/01/08 Javascript
jQuery通过改变input的type属性实现密码显示隐藏切换功能
2017/02/08 Javascript
JS实现线性表的顺序表示方法示例【经典数据结构】
2017/04/11 Javascript
微信小程序动态显示项目倒计时效果
2017/06/13 Javascript
JavaScript中正则表达式判断匹配规则及常用方法
2017/08/03 Javascript
Vue中render函数的使用方法
2018/01/31 Javascript
nodejs实现用户登录路由功能
2019/05/22 NodeJs
jQuery与原生JavaScript选择HTML元素集合用法对比分析
2019/11/26 jQuery
[01:16:50]DOTA2-DPC中国联赛 正赛 Phoenix vs CDEC BO3 第一场 3月7日
2021/03/11 DOTA
Python中itertools模块用法详解
2014/09/25 Python
python执行使用shell命令方法分享
2017/11/08 Python
python去除拼音声调字母,替换为字母的方法
2018/11/28 Python
对Python 除法负数取商的取整方式详解
2018/12/12 Python
python pillow库的基础使用教程
2021/01/13 Python
CSS3等相关属性制作分页导航实现代码
2012/12/24 HTML / CSS
css3实现简单的白云飘动背景特效
2020/10/28 HTML / CSS
详解如何使用rem或viewport进行移动端适配
2020/08/14 HTML / CSS
自荐信的五个重要部分
2013/10/29 职场文书
优良学风班申请材料
2014/02/13 职场文书
pytorch实现加载保存查看checkpoint文件
2022/07/15 Python