详解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下对于事件、事件流、事件触发的顺序随便说说
Jul 17 Javascript
详谈 Jquery Ajax异步处理Json数据.
Sep 09 Javascript
JS实现距离上次刷新已过多少秒示例
May 23 Javascript
Javascript中String的常用方法实例分析
Jun 13 Javascript
浅析JavaScript 箭头函数 generator Date JSON
May 23 Javascript
Highcharts学习之坐标轴
Aug 02 Javascript
js鼠标经过tab选项卡时实现切换延迟
Mar 24 Javascript
在一般处理程序(ashx)中弹出js提示语
Aug 16 Javascript
微信小程序实现通过双向滑动缩放图片大小的方法
Dec 30 Javascript
详解如何在Vue项目中导出Excel
Apr 19 Javascript
Vue ElementUI实现:限制输入框只能输入正整数的问题
Jul 31 Javascript
Html5生成验证码的示例代码
May 10 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+Mysql+jQuery实现动态展示信息
2011/10/08 PHP
Fedora下安装php Redis扩展笔记
2014/09/03 PHP
CI操作cookie的方法分析(基于helper类库)
2016/03/28 PHP
List the Codec Files on a Computer
2007/06/11 Javascript
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
2014/09/26 NodeJs
使用js画图之正弦曲线
2015/01/12 Javascript
jquery中change()用法实例分析
2015/02/06 Javascript
总结JavaScript设计模式编程中的享元模式使用
2016/05/21 Javascript
微信小程序 教程之事件
2016/10/18 Javascript
JQuery validate 验证一个单独的表单元素实例
2017/02/17 Javascript
Vue计算属性的使用
2017/08/04 Javascript
JavaScript实现与使用发布/订阅模式详解
2019/01/19 Javascript
vue-cli脚手架引入弹出层layer插件的几种方法
2019/06/24 Javascript
微信小程序入口场景的问题集合与相关解决方法
2019/06/26 Javascript
小程序新版订阅消息模板消息
2019/12/31 Javascript
浅谈webpack构建工具配置和常用插件总结
2020/05/11 Javascript
浅谈vue 多个变量同时赋相同值互相影响
2020/08/05 Javascript
python查询mysql中文乱码问题
2014/11/09 Python
Python中if __name__ == '__main__'作用解析
2015/06/29 Python
python运行其他程序的实现方法
2017/07/14 Python
Python中turtle作图示例
2017/11/15 Python
Python实现Pig Latin小游戏实例代码
2018/02/02 Python
简单了解django索引的相关知识
2019/07/17 Python
基于Django静态资源部署404的解决方法
2019/07/28 Python
Python tkinter模版代码实例
2020/02/05 Python
Pycharm中如何关掉python console
2020/10/27 Python
Pycharm创建python文件自动添加日期作者等信息(步骤详解)
2021/02/03 Python
HTML5中indexedDB 数据库的使用实例
2017/05/11 HTML / CSS
HTML5 Canvas 旋转风车绘制
2017/08/18 HTML / CSS
HTML5 图片悬停放大的实现代码示例
2019/12/04 HTML / CSS
新奇的小玩意:IWOOT
2016/07/21 全球购物
如果NULL定义成#define NULL((char *)0)难道不就可以向函数传入不加转换的NULL了吗
2012/02/15 面试题
介绍一下Transact-SQL中SPACE函数的用法
2015/09/01 面试题
《社戏》教学反思
2014/04/15 职场文书
研究生简历自我评
2015/03/11 职场文书
Android开发EditText禁止输入监听及InputFilter字符过滤
2022/06/10 Java/Android