详解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 hashtable实现代码
Oct 13 Javascript
caller和callee的区别介绍及演示结果
Mar 10 Javascript
jQuery的3种请求方式$.post,$.get,$.getJSON
Mar 28 Javascript
javascript实现des解密加密全过程
Apr 03 Javascript
Javascript玩转继承(二)
May 08 Javascript
Node.js(安装,启动,测试)
Jun 09 Javascript
JavaScript函数详解
Nov 17 Javascript
详解javascript的变量与标识符
Jan 04 Javascript
JavaScript简单计算人的年龄示例
Apr 15 Javascript
Mui使用jquery并且使用点击跳转新窗口的实例
Aug 19 jQuery
Vue基于NUXT的SSR详解
Oct 24 Javascript
用React Native制作一个简单的游戏引擎
May 27 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一个名片库程序
2006/10/09 PHP
php读取javascript设置的cookies的代码
2010/04/12 PHP
有关PHP中MVC的开发经验分享
2012/05/17 PHP
php curl模拟post提交数据示例
2013/12/31 PHP
php生成静态页面的简单示例
2014/04/17 PHP
使用Javascript接收get传递的值的代码
2011/11/30 Javascript
使用AngularJS创建单页应用的编程指引
2015/06/19 Javascript
js淡入淡出的图片轮播效果代码分享
2015/08/24 Javascript
20分钟轻松创建自己的Bootstrap站点
2016/05/12 Javascript
jquery自定义表单验证插件
2016/10/12 Javascript
详解.vue文件中监听input输入事件(oninput)
2017/09/19 Javascript
基于Vue组件化的日期联动选择器功能的实现代码
2018/11/30 Javascript
微信小程序时间控件picker view使用详解
2018/12/28 Javascript
python实现爬虫下载美女图片
2015/07/14 Python
python实现将多个文件分配到多个文件夹的方法
2019/01/07 Python
Django实现简单网页弹出警告代码
2019/11/15 Python
在OpenCV里使用Camshift算法的实现
2019/11/22 Python
Python如何爬取qq音乐歌词到本地
2020/06/01 Python
用python-webdriver实现自动填表的示例代码
2021/01/13 Python
Julep官网:美容产品和指甲油
2017/02/25 全球购物
UGG美国官网:购买UGG雪地靴、拖鞋和鞋子
2017/12/31 全球购物
.NET面试题:什么是反射
2016/09/30 面试题
如何写出高质量、高性能的MySQL查询
2014/11/17 面试题
计算机应用毕业生自荐信
2013/10/23 职场文书
高一英语教学反思
2014/01/22 职场文书
岗位职责的构建方法
2014/02/01 职场文书
经典婚礼主持开场白
2014/03/13 职场文书
导游个人求职信范文
2014/03/23 职场文书
机关会计岗位职责
2014/04/08 职场文书
个人委托书范本
2014/09/13 职场文书
支行行长竞聘报告
2014/11/06 职场文书
2015年党支部书记工作总结
2015/05/21 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
检讨书怎么写?
2019/06/21 职场文书
CSS实现隐藏搜索框功能(动画正反向序列)
2021/07/21 HTML / CSS
table不让td文字溢出操作方法
2022/12/24 HTML / CSS