JavaScript解决浮点数计算不准确问题的方法分析


Posted in Javascript onJuly 09, 2018

本文实例讲述了JavaScript解决浮点数计算不准确问题的方法。分享给大家供大家参考,具体如下:

最近在学习electron框架,想利用这个框架做一个简单的计算器demo。当我对小数进行运算时,发现了一个问题。

0.1+0.2=?

输出结果是:0.30000000000000004

为什么会这样呢?

其实对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。

首先我们分析一下为什么会出现这个精度误差?

首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:

0.1 => 0.0001 1001 1001 1001..(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)

上面我们发现0.1和0.2转化为二进制之后,变成了一个无限循环的数字,这在现实生活中,无限循环我们可以理解,但计算机是不允许无限循环的,对于无限循环的小数,计算机会进行舍入处理。进行双精度浮点数的小数部分最多支持52位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。

知道了浮点数产生的原因,那么如何处理这个问题呢?

方法1:通过toFixed(num)方法来保留小数。因为这个方法是根据四舍五入来保留小数的,所以最后的计算结果不精确。

方法2:把要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,计算完以后再降级,推荐使用这一种方法。具体代码如下(主要有3个方法):

/*判断obj是否为一个整数*/
function isInteger(obj){
  return Math.floor(obj) === obj;
}
/**
* 将一个浮点数转换成整数,返回整数和倍数
* 如 3.14 》》314 倍数是100
*
*/
function toInteger(floatNum){
  var ret = {times:1,num:0};
  //是整数
  if(isInteger(floatNum)){
    ret.num = floatNum;
    return ret;
  }
  var strfi = floatNum + '';
  //查找小数点的下标
  var dotPos = strfi.indexOf('.');
  console.log('dotPos===='+dotPos);
  //获取小数的位数
  var len = strfi.substr(dotPos+1).length;
  console.log('len===='+len);
  //Math.pow(10,len)指定10的len次幂。
  var time = Math.pow(10,len);
  //将浮点数转化为整数
  var intNum = parseInt(floatNum*time + 0.5,10);
  console.log('intNum===='+intNum);
  ret.times = time;
  ret.num = intNum;
  return ret;
}
/**
*进行运算
*三个参数分别是要运算的两个数和运算符
*/
function operation(a,b,op){
  var o1 = toInteger(a);
  var o2 = toInteger(b);
  var n1 = o1.num;
  var n2 = o2.num;
  var t1 = o1.times;
  var t2 = o2.times;
  var max = t1 > t2 ? t1 : t2;
  var result = null;
  switch(op){
    case 'add':
      if(t1 === t2){
        result = n1 + n2;
      }else if(t1 > t2){
        result = n1 + n2 * (t1/t2);
      }else{
        result = n1 * (t2/t1) + n2;
      }
      return result / max;
      break;
    case 'subtract':
      if(t1 === t2){
        result = n1 - n2;
      }else if(t1 > t2){
        result = n1 - n2 * (t1/t2);
      }else{
        result = n1 * (t2/t1) - n2;
      }
      return result / max;
      break;
    case 'multiply':
      result = (n1 * n2)/(t1 * t2);
      return result;
      break;
    case 'divide':
      result = (n1 / n2)/(t2 / t1);
      return result;
      break;
  }
}

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
在线编辑器的实现原理(兼容IE和FireFox)
Mar 09 Javascript
JS在IE和FF下attachEvent,addEventListener学习笔记
Nov 26 Javascript
JS图片无缝滚动(简单利于使用)
Jun 17 Javascript
jQuery实现图片信息的浮动显示实例代码
Aug 28 Javascript
Jquery attr("checked") 返回checked或undefined 获取选中失效
Oct 10 Javascript
Express实现前端后端通信上传图片之存储数据库(mysql)傻瓜式教程(二)
Dec 10 Javascript
Bootstrap布局方式详解
May 27 Javascript
JavaScript程序中实现继承特性的方式总结
Jun 24 Javascript
基于LayUI分页和LayUI laypage分页的使用示例
Aug 02 Javascript
layui数据表格实现重载数据表格功能(搜索功能)
Jul 27 Javascript
Vue的click事件防抖和节流处理详解
Nov 13 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
Feb 26 Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 #Javascript
JavaScript实现创建自定义对象的常用方式总结
Jul 09 #Javascript
vue-cli配置环境变量的方法
Jul 09 #Javascript
JS逻辑运算符短路操作实例分析
Jul 09 #Javascript
微信小程序中时间戳和日期的相互转换问题
Jul 09 #Javascript
使用async await 封装 axios的方法
Jul 09 #Javascript
bootstrap 弹出框modal添加垂直方向滚轴效果
Jul 09 #Javascript
You might like
PHP中static关键字原理的学习研究分析
2011/07/18 PHP
PHP实现在线阅读PDF文件的方法
2015/06/17 PHP
laravel框架数据库操作、查询构建器、Eloquent ORM操作实例分析
2019/12/20 PHP
jQuery 各种浏览器下获得日期区别
2008/12/22 Javascript
NodeJS的模块写法入门(实例代码)
2012/03/07 NodeJs
jQuery动画与特效详解
2015/02/01 Javascript
JS实现控制表格行内容垂直对齐的方法
2015/03/30 Javascript
JavaScript检测字符串中是否含有html标签实现方法
2015/07/01 Javascript
基于jquery实现轮播特效
2016/04/22 Javascript
JavaScript中的call和apply的用途以及区别
2017/01/11 Javascript
JavaScript严格模式详解
2017/01/16 Javascript
Node.js 异步异常的处理与domain模块解析
2017/05/10 Javascript
AngularJS入门教程一:路由用法初探
2017/05/27 Javascript
Angular在模板驱动表单中自定义校验器的方法
2017/08/09 Javascript
vue2.0模拟锚点的实例
2018/03/14 Javascript
Vue Element 分组+多选+可搜索Select选择器实现示例
2018/07/23 Javascript
html+jQuery实现拖动滑块图片拼图验证码插件【移动端适用】
2019/09/10 jQuery
Node如何后台数据库使用增删改查功能
2019/11/21 Javascript
基于JavaScript实现猜数字游戏代码实例
2020/07/30 Javascript
vue 动态添加的路由页面刷新时失效的原因及解决方案
2021/02/26 Vue.js
Python中的闭包总结
2014/09/18 Python
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
2015/05/05 Python
Python随机生成手机号、数字的方法详解
2017/07/21 Python
python实现文件助手中查看微信撤回消息
2019/04/29 Python
Django表单提交后实现获取相同name的不同value值
2020/05/14 Python
HTML5 和小程序实现拍照图片旋转、压缩和上传功能
2018/10/08 HTML / CSS
英国和世界各地鲜花速递专家:Arena Flowers
2018/02/10 全球购物
应届大学生求职信
2013/12/01 职场文书
大学优秀班主任事迹材料
2014/05/02 职场文书
学生不讲诚信检讨书
2014/09/29 职场文书
房屋财产继承协议书范本
2014/11/03 职场文书
会计岗位职责范本
2015/04/02 职场文书
企业爱心捐款倡议书
2015/04/27 职场文书
喋血孤城观后感
2015/06/08 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书
Golang ort 中的sortInts 方法
2022/04/24 Golang