详解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 添加和移除函数的通用方法
Oct 20 Javascript
jquery中实现标签切换效果的代码
Mar 01 Javascript
jQuery zTree加载树形菜单功能
Feb 25 Javascript
BootstrapTable与KnockoutJS相结合实现增删改查功能【二】
May 10 Javascript
Angularjs过滤器使用详解
May 25 Javascript
jQuery替换节点用法示例(使用replaceWith方法)
Sep 08 Javascript
js仿微信语音播放实现思路
Dec 12 Javascript
vue构建单页面应用实战
Apr 10 Javascript
简述jQuery Easyui一些用法
Aug 01 jQuery
AngularJS表单验证功能
Oct 19 Javascript
使用 Node.js 实现图片的动态裁切及算法实例代码详解
Sep 29 Javascript
使用nvm和nrm优化node.js工作流的方法
Jan 17 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 microtime获取浮点的时间戳
2010/02/21 PHP
PHP6连接SQLServer2005的三部曲
2016/04/15 PHP
PHP生成短网址方法汇总
2016/07/12 PHP
javascript+dom树型菜单类,希望朋友们一起进步
2007/05/03 Javascript
谷歌地图打不开的解决办法
2014/08/07 Javascript
jQuery实现瀑布流的取巧做法分享
2015/01/12 Javascript
JS建造者模式基本用法实例分析
2015/06/30 Javascript
详解AngularJS Filter(过滤器)用法
2015/12/28 Javascript
解析Javascript单例模式概念与实例
2016/12/05 Javascript
bootstrap table实例详解
2017/01/06 Javascript
扩展bootstrap的modal模态框-动态添加modal框-弹出多个modal框
2017/02/21 Javascript
JS闭包可被利用的常见场景小结
2017/04/09 Javascript
浅谈react.js中实现tab吸顶效果的问题
2017/09/06 Javascript
react+redux的升级版todoList的实现
2017/12/18 Javascript
vue弹窗组件的实现示例代码
2018/09/10 Javascript
浅谈webpack性能榨汁机(打包速度优化)
2019/01/09 Javascript
vue子组件改变父组件传递的prop值通过sync实现数据双向绑定(DEMO)
2020/02/01 Javascript
Python检测一个对象是否为字符串类的方法
2015/05/21 Python
python实现简单神经网络算法
2018/03/10 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
2019/01/22 Python
Python发展简史 Python来历
2019/05/14 Python
Python3 集合set入门基础
2020/02/10 Python
Python request使用方法及问题总结
2020/04/26 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
2020/05/19 Python
详解HTML5中的Communication API基本使用方法
2016/01/29 HTML / CSS
对祖国的寄语大全
2014/04/11 职场文书
学生操行评语大全
2014/04/24 职场文书
企业管理标语
2014/06/10 职场文书
2014教育局对照检查材料思想汇报
2014/09/23 职场文书
护士节慰问信
2015/02/15 职场文书
2019年冬至:天冷暖人心的问候祝福语大全
2019/12/20 职场文书
还在手动盖楼抽奖?教你用Python实现自动评论盖楼抽奖(一)
2021/06/07 Python
分析JVM源码之Thread.interrupt系统级别线程打断
2021/06/29 Java/Android
看完这篇文章获得一些java if优化技巧
2021/07/15 Java/Android
nginx安装以及配置的详细过程记录
2021/09/15 Servers
golang连接MySQl使用sqlx库
2022/04/14 Golang