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 相关文章推荐
控制打印时页眉角的代码
Feb 08 Javascript
JQuery 学习笔记 选择器之一
Jul 23 Javascript
JavaScript 面向对象的 私有成员和公开成员
May 13 Javascript
JQuery+CSS提示框实现思路及代码(纯手工打造)
May 07 Javascript
zTree插件之多选下拉菜单实例代码
Nov 06 Javascript
jquery为页面增加快捷键示例
Jan 31 Javascript
JS获得图片alt信息的方法
Apr 01 Javascript
将页面table内容与样式另存成excel文件的方法
Aug 05 Javascript
js实现的后台左侧管理菜单代码
Sep 11 Javascript
实例讲解js验证表单项是否为空的方法
Jan 09 Javascript
javascript实现电脑和手机版样式切换
Nov 10 Javascript
利用JavaScript缓存远程窃取Wi-Fi密码的思路详解
Nov 05 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
C# Assembly类访问程序集信息
2009/06/13 PHP
PHP 中文乱码解决办法总结分析
2009/07/30 PHP
PHP代码实现爬虫记录――超管用
2015/07/31 PHP
thinkphp3.2.0 setInc方法 源码全面解析
2018/01/29 PHP
加速IE的Javascript document输出的方法
2010/12/02 Javascript
JS无限树状列表实现代码
2011/01/11 Javascript
JavaScript中的稀疏数组与密集数组[译]
2012/09/17 Javascript
jQuery实现下拉框左右选择的简单实例
2014/02/22 Javascript
js实现浏览本地文件并显示扩展名的方法
2015/08/17 Javascript
js获取隐藏元素宽高的实现方法
2016/05/19 Javascript
jquery中取消和绑定hover事件的实现代码
2016/06/02 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
2017/01/01 Javascript
原生js实现无缝轮播图效果
2017/01/11 Javascript
Vue路由跳转问题记录详解
2017/06/15 Javascript
JS实现留言板功能
2017/06/17 Javascript
bootstrap-table组合表头的实现方法
2017/09/07 Javascript
web前端vue实现插值文本和输出原始html
2018/01/19 Javascript
Vue列表渲染的示例代码
2018/11/01 Javascript
JS实现简单的点赞与踩功能示例
2018/12/05 Javascript
vue实现动态给id赋值,点击事件获取当前点击的元素的id操作
2020/11/09 Javascript
Python中非常实用的一些功能和函数分享
2015/02/14 Python
多版本Python共存的配置方法
2017/05/22 Python
Python编程之序列操作实例详解
2017/07/22 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
python绘制圆柱体的方法
2018/07/02 Python
Python使用sort和class实现的多级排序功能示例
2018/08/15 Python
windows下搭建python scrapy爬虫框架步骤
2018/12/23 Python
Python socket模块实现的udp通信功能示例
2019/04/10 Python
Python计算公交发车时间的完整代码
2020/02/12 Python
tensorflow安装成功import tensorflow 出现问题
2020/04/16 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
教师旷工检讨书
2014/01/18 职场文书
民间借贷纠纷起诉书
2015/08/03 职场文书
幽默导游词应该怎么写?
2019/08/26 职场文书
Python激活Anaconda环境变量的详细步骤
2021/06/08 Python
html5 录制mp3音频支持采样率和比特率设置
2021/07/15 Javascript