详解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 相关文章推荐
fancybox1.3.1 基于Jquery的插件在IE中图片显示问题
Oct 01 Javascript
JavaScript中使用正则匹配多条,且获取每条中的分组数据
Nov 30 Javascript
非常强大的 jQuery.AsyncBox 弹出对话框插件
Aug 29 Javascript
jquery焦点图片切换(数字标注/手动/自动播放/横向滚动)
Jan 24 Javascript
jQuery过滤选择器详解
Jan 13 Javascript
js实现鼠标经过时图片滚动停止的方法
Feb 16 Javascript
JavaScript实现的字符串replaceAll函数代码分享
Apr 02 Javascript
JavaScript实现计算多边形质心的方法示例
Jan 31 Javascript
使用webpack打包koa2 框架app
Feb 02 Javascript
vue.js动画中的js钩子函数的实现
Jul 06 Javascript
微信小程序实现之手势锁功能实例代码
Jul 19 Javascript
如何使用RoughViz可视化Vue.js中的草绘图表
Jan 30 Vue.js
实现隔行换色效果的两种方式【实用】
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错误和异长常处理总结
2014/03/06 PHP
PHP排序算法类实例
2015/06/17 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
Laravel中注册Facades的步骤详解
2016/03/16 PHP
mouse_on_title.js
2006/08/25 Javascript
ImageZoom 图片放大镜效果(多功能扩展篇)
2010/04/14 Javascript
Extjs4 关于Store的一些操作(加载/回调/添加)
2013/04/18 Javascript
js中的scroll和offset 使用比较的实例与分析
2013/09/29 Javascript
JS将表单导出成EXCEL的实例代码
2013/11/11 Javascript
Jqgrid表格随窗口大小改变而改变的简单实例
2013/12/28 Javascript
浅析JS中document对象的一些重要属性
2014/03/06 Javascript
使用jquery实现放大镜效果
2014/09/02 Javascript
浅析javascript操作 cookie对象
2014/12/26 Javascript
vue引入swiper插件的使用实例
2017/07/19 Javascript
bootstrap响应式导航条模板使用详解(含下拉菜单,弹出框)
2017/11/17 Javascript
如何用JavaScript实现功能齐全的单链表详解
2019/02/11 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
在vue-cli创建的项目中使用sass操作
2020/08/10 Javascript
vue组件中实现嵌套子组件案例
2020/08/31 Javascript
[40:27]完美世界DOTA2联赛PWL S3 PXG vs GXR 第一场 12.19
2020/12/24 DOTA
Python中捕捉详细异常信息的代码示例
2014/09/18 Python
python实现聊天小程序
2018/03/13 Python
python实现输入三角形边长自动作图求面积案例
2020/04/12 Python
东南亚地区最大的购物网站Lazada新加坡站点:Lazada.sg
2016/07/17 全球购物
美国时尚在线:Showpo
2017/09/08 全球购物
你所在的项目是如何确定版本号的
2015/12/28 面试题
个人简历中的自我评价范例
2013/10/29 职场文书
水务局局长岗位职责
2013/11/28 职场文书
分公司经理任命书
2014/06/05 职场文书
在职员工证明书
2014/09/19 职场文书
六五普法先进个人主要事迹材料
2015/11/03 职场文书
立秋之描写立秋的作文(五年级)
2019/08/08 职场文书
Mysql存储过程、触发器、事件调度器使用入门指南
2022/01/22 MySQL
基于Python实现一个春节倒计时脚本
2022/01/22 Python
CSS3实现指纹特效代码
2022/03/17 HTML / CSS
python如何利用cv2.rectangle()绘制矩形框
2022/12/24 Python