详解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 相关文章推荐
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 Javascript
JS函数实现动态添加CSS样式表文件
Dec 15 Javascript
java和javascript获取word文档的书签位置对比
Jun 19 Javascript
JS实现简易图片轮播效果的方法
Mar 25 Javascript
jQuery实现图片加载完成后改变图片大小的方法
Mar 29 Javascript
浅谈js函数三种定义方式 & 四种调用方式 & 调用顺序
Feb 19 Javascript
js实现数字递增特效【仿支付宝我的财富】
May 05 Javascript
JavaScript实现带有子菜单和控件的slider轮播图效果
Nov 01 Javascript
手把手教你写一个微信小程序(推荐)
Oct 17 Javascript
Vue Extends 扩展选项用法完整实例
Sep 17 Javascript
解决Vue的项目使用Element ui 走马灯无法实现的问题
Aug 03 Javascript
Vue基于localStorage存储信息代码实例
Nov 16 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的正则处理函数总结分析
2008/06/20 PHP
php URL验证正则表达式
2011/07/19 PHP
自己写了一个php检测文件编码的函数
2014/04/21 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
PHP正则替换函数preg_replace()报错:Notice Use of undefined constant的解决方法分析
2017/02/04 PHP
PHP的中使用非缓冲模式查询数据库的方法
2017/02/05 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
PHP使用curl_multi_select解决curl_multi网页假死问题的方法
2018/08/15 PHP
JS在IE下缺少标识符的错误
2014/07/23 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
JS中判断null的方法分析
2016/11/21 Javascript
JS/jquery实现一个网页内同时调用多个倒计时的方法
2017/04/27 jQuery
Vue利用History记录上一页面的数据方法实例
2018/11/02 Javascript
vue-router跳转时打开新页面的两种方法
2019/07/29 Javascript
vue自动添加浏览器兼容前后缀操作
2020/08/13 Javascript
微信小程序实现点击页面出现文字
2020/09/21 Javascript
vue+elementUI动态增加表单项并添加验证的代码详解
2020/12/17 Vue.js
[06:10]6.81新信使新套装!给你一个炫酷的DOTA2
2014/05/06 DOTA
[01:28]2014DOTA2国际邀请赛中国区预选赛四大豪门直升机抵达会场
2014/05/24 DOTA
python 装饰器功能以及函数参数使用介绍
2012/01/27 Python
python创建和删除目录的方法
2015/04/29 Python
python实现自动化上线脚本的示例
2019/07/01 Python
Python超越函数积分运算以及绘图实现代码
2019/11/20 Python
六种酷炫Python运行进度条效果的实现代码
2020/07/17 Python
Python中用xlwt制作表格实例讲解
2020/11/05 Python
HTML5离线缓存在tomcat下部署可实现图片flash等离线浏览
2012/12/13 HTML / CSS
HTML5 video标签(播放器)学习笔记(二):播放控制
2015/04/24 HTML / CSS
3种方式实现瀑布流布局小结
2019/09/05 HTML / CSS
数控专业大学毕业生职业规划范文
2014/02/06 职场文书
企业总经理任命书
2014/06/05 职场文书
上班时间打瞌睡检讨书
2014/09/26 职场文书
《改造我们的学习》心得体会
2014/11/07 职场文书
WordPress多语言翻译插件 - WPML使用教程
2021/04/01 PHP
深入讲解Vue中父子组件通信与事件触发
2022/03/22 Vue.js
python绘制云雨图raincloud plot
2022/08/05 Python