详解JS-- 浮点数运算处理


Posted in Javascript onNovember 28, 2016

一. 问题描述

最近在做一个项目,页面上会存在一些JS浮点数的运算,发现JS浮点数运算存在一些bug.譬如:

0.1+0.2 == 0.30000000000000004
 
0.1 + 0.7 == 0.7999999999999999
 
7*0.8 == 5.6000000000000005
 
5.6/7 == 0.7999999999999999

二.解决方案

 

JS运算后都会有很小的误差. 不像.Net或者Java那样准确. 主要是JS重点不在运算上面,可是有时候项目一定要用到.想了一下大概有两种解决方案

A 方案一:

运算结果保留2-3位小数位数. 前端界面一般用到的运算比较少。精度要求不会太高。 所以取2位小数位即可。

B. 方案二:

将小数位数转换为整数运算. 譬如:

0.1+0.2 =》 (1+2)/10 == 0.3
 
0.1 + 0.7 =》 (1+7)/10 == 0.8
 
7*0.8 == (7*8)/10 == 5.6
 
5.6/7 == (56/7)/10 == 0.1

为了方便调用. 所以我们可以提取一个公共的方法出来.譬如下面的JSMath库,JSMath重写了加减乘除. 会先将参数转换为整数再运算JSMath(参数1).操作(参数2)

参数1和参数2分别就是运算的第一个Number和第二个Number. 计算后通过Value属性获取值.

(function() {
 
  var JSMath = function() {
    return this;
  }
 
  JSMath.prototype.from = function(value) {
 
    // 支持JSMath参数传递主要是用于嵌套的调用
    if ((typeof(value) == 'object') && (value.value != undefined)) {
      this.value = value.value;
    } else {
      this.value = value;
    }
    return this;
  }
 
  // 加法
  JSMath.prototype.add = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value + Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount);
    return this;
  }
 
 // 减法
  JSMath.prototype.sub = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value - Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount);
    return this;
  }
 
  // 除法

  JSMath.prototype.div = function(value) {
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = ((Math.pow(10, maxtimeCount) * this.value) / (Math.pow(10, maxtimeCount) * value));
    return this;
  }
 
  // 乘法
  JSMath.prototype.times = function(value) {
 
    var thisValueString = this.value.toString();
    var valueString = value.toString();
    var timesCount1 = 0;
    var timesCount2 = 0;
    if (thisValueString.indexOf('.') > 0) {
      timesCount1 = thisValueString.split('.')[1].length;
    }
    if (valueString.indexOf('.') > 0) {
      timesCount2 = valueString.split('.')[1].length;
    }
    var maxtimeCount = timesCount1 > timesCount2 ? timesCount1 : timesCount2;
    this.value = (Math.pow(10, maxtimeCount) * this.value * Math.pow(10, maxtimeCount) * value) / Math.pow(10, maxtimeCount * 2);
    return this;
  }
 
  if (window.JSMath == undefined) {
    window.JSMath = function(value) {
      var result = new JSMath();
      result.from(value);
      return result;
    }
  }
})()

B1.基本运算

0.1+0.2
=> JSMath(0.1).add(0.2).value == 0.3
 
7+0.8
=> JSMath(7).times(0.8).value == 5.6
 
5.6/7
=> JSMath(5.6).div(7).value = 0.8

B2.多目运算

0.05 + 0.05 + 0.2
=> JSMath(JSMath(0.05).add(0.05)).add(0.2).value == 0.3
 
(5+0.6)/7
=> JSMath(JSMath(5).add(0.6)).div(7).value == 0.8

三.小总结

上面自己自己暂时知道的一些解决方案.不太清楚是否有开源的更可靠的三方库来解决这个问题。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 动态创建VML的方法
Oct 14 Javascript
jQuery EasyUI API 中文文档 - NumberBox数字框
Oct 13 Javascript
jQuery .attr()和.removeAttr()方法操作元素属性示例
Jul 16 Javascript
javascript中直接引用Microsoft的COM生成Word
Jan 20 Javascript
js实现点击链接后延迟3秒再跳转的方法
Jun 05 Javascript
分享五个有用的jquery小技巧
Oct 08 Javascript
基于Vuejs实现购物车功能
Aug 02 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
Nov 23 Javascript
用jQuery实现优酷首页轮播图
Jan 09 Javascript
JavaScript常用事件介绍
Jan 21 Javascript
element-ui上传一张图片后隐藏上传按钮功能
May 22 Javascript
微信小程序以ssm做后台开发的实现示例
Apr 08 Javascript
实现隔行换色效果的两种方式【实用】
Nov 27 #Javascript
javascript实现无法关闭的弹框
Nov 27 #Javascript
js格式化时间的简单实例
Nov 27 #Javascript
浅谈jquery页面初始化的4种方式
Nov 27 #Javascript
js实现页面刷新滚动条位置不变
Nov 27 #Javascript
Javascrip实现文字跳动特效
Nov 27 #Javascript
JavaScript 监控微信浏览器且自带返回按钮时间
Nov 27 #Javascript
You might like
php中使用ExcelFileParser处理excel获得数据(可作批量导入到数据库使用)
2010/08/21 PHP
php模拟socket一次连接,多次发送数据的实现代码
2011/07/26 PHP
php中将指针移动到数据集初始位置的实现代码[mysql_data_seek]
2012/11/01 PHP
PHP创建word文档的方法(平台无关)
2016/03/29 PHP
JS获取IP、MAC和主机名的五种方法
2013/11/14 Javascript
关于JavaScript对象的动态选择及遍历对象
2014/03/10 Javascript
get(0).tagName获得作用标签示例代码
2014/10/08 Javascript
jQuery获得包含margin的outerWidth和outerHeight的方法
2015/03/25 Javascript
jQuery基于ajax实现带动画效果无刷新柱状图投票代码
2015/08/10 Javascript
Cookies 和 Session的详解及区别
2017/04/21 Javascript
protractor的安装与基本使用教程
2017/07/07 Javascript
Vue2.0基于vue-cli+webpack同级组件之间的通信教程(推荐)
2017/09/14 Javascript
javascript用rem来做响应式开发
2018/01/13 Javascript
Vuex的基本概念、项目搭建以及入坑点
2018/11/04 Javascript
vue下拉菜单组件(含搜索)的实现代码
2018/11/25 Javascript
Layer.js实现表格溢出内容省略号显示,悬停显示全部的方法
2019/09/16 Javascript
vue实现跳转接口push 转场动画示例
2019/11/01 Javascript
详解python3中tkinter知识点
2018/06/21 Python
python实现windows壁纸定期更换功能
2019/01/21 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
2019/11/15 Python
python中从for循环延申到推导式的具体使用
2019/11/29 Python
python3中使用__slots__限定实例属性操作分析
2020/02/14 Python
Python ATM功能实现代码实例
2020/03/19 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
TensorFlow固化模型的实现操作
2020/05/26 Python
canvas画布实现手写签名效果的示例代码
2019/04/23 HTML / CSS
美国大城市最热门旅游景点门票:CityPASS
2016/12/16 全球购物
英国最大的在线床超市:Bed Star
2019/01/24 全球购物
澳大利亚波西米亚风连衣裙在线商店:Fortunate One
2019/04/01 全球购物
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
员工自我评价范文
2015/03/11 职场文书
2015领导干部廉洁自律工作总结
2015/07/23 职场文书
党组织关系的介绍信模板
2019/06/21 职场文书
MySQL数据库压缩版本安装与配置详细教程
2021/05/21 MySQL
CentOS7安装GlusterFS集群以及相关配置
2022/04/12 Servers
python缺失值填充方法示例代码
2022/12/24 Python