详解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 相关文章推荐
使用jquery给input和textarea设定ie中的focus
May 29 Javascript
Js放到HTML文件中的哪个位置有什么区别
Aug 21 Javascript
Jquery获得控件值的三种方法总结
Feb 13 Javascript
完美兼容各大浏览器的jQuery仿新浪图文淡入淡出间歇滚动特效
Nov 12 Javascript
如何利用模板将HTML从JavaScript中抽离
Oct 08 Javascript
JS实现倒计时(天数、时、分、秒)
Nov 16 Javascript
常用的javascript设计模式
Jan 11 Javascript
写jQuery插件时的注意点
Feb 20 Javascript
关于vue.js v-bind 的一些理解和思考
Jun 06 Javascript
关于在mongoose中填充外键的方法详解
Aug 14 Javascript
angularjs实现分页和搜索功能
Jan 03 Javascript
fastadmin中调用js的方法
May 14 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
vs中通过剪切板循环来循环粘贴不同内容
2011/04/30 PHP
防止本地用户用fsockopen DDOS攻击对策
2011/11/02 PHP
提高PHP编程效率的方法
2013/11/07 PHP
JQuery 常用方法和事件详细介绍
2013/04/18 Javascript
js 判断文件类型并控制表单提交示例代码
2013/11/14 Javascript
Node.js中的缓冲与流模块详细介绍
2015/02/11 Javascript
jquery 插件实现瀑布流图片展示实例
2015/04/03 Javascript
基于jQuery实现Accordion手风琴自定义插件
2020/10/13 Javascript
JavaScript的事件机制详解
2017/01/17 Javascript
JS实现的按钮点击颜色切换功能示例
2017/10/19 Javascript
微信小程序实现图片懒加载的示例代码
2017/12/13 Javascript
使用Vuex实现一个笔记应用的方法
2018/03/13 Javascript
微信小程序下拉框组件使用方法详解
2018/12/28 Javascript
微信小程序封装的HTTP请求示例【附升级版】
2019/05/11 Javascript
vue实现按需加载组件及异步组件功能
2019/05/27 Javascript
防止Layui form表单重复提交的实现方法
2019/09/10 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
2020/05/03 Javascript
详解vue路由
2020/08/05 Javascript
django实现前后台交互实例
2017/08/07 Python
python tensorflow学习之识别单张图片的实现的示例
2018/02/09 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
2018/04/17 Python
Python实现删除时保留特定文件夹和文件的示例
2018/04/27 Python
python实现决策树分类(2)
2018/08/30 Python
python统计中文字符数量的两种方法
2019/01/31 Python
将pip源更换到国内镜像的详细步骤
2019/04/07 Python
简单了解python 邮件模块的使用方法
2019/07/24 Python
Python list与NumPy array 区分详解
2019/11/06 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
python asyncio 协程库的使用
2021/01/21 Python
详解Html5页面实现下载文件(apk、txt等)的三种方式
2018/10/22 HTML / CSS
简历中自我评价范文3则
2013/12/14 职场文书
环保倡议书100字
2014/05/15 职场文书
带刀到教室的检讨书
2014/10/04 职场文书
python实现求纯色彩图像的边框
2021/04/08 Python
Oracle 临时表空间SQL语句的实现
2021/09/25 Oracle
JavaScript最完整的深浅拷贝实现方式详解
2022/02/28 Javascript