详解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 的Document属性和方法集合
Jan 25 Javascript
JavaScript中的cacheStorage使用详解
Jul 29 Javascript
angularjs学习笔记之双向数据绑定
Sep 26 Javascript
JavaScript提高网站性能优化的建议(二)
Jul 24 Javascript
JS简单实现点击跳转登陆邮箱功能的方法
Oct 31 Javascript
vue-awesome-swiper滑块插件使用方法详解
Nov 27 Javascript
在vue-cli搭建的项目中增加后台mock接口的方法
Apr 26 Javascript
使用JavaScript解析URL的方法示例
Mar 01 Javascript
javascript实现自由编辑图片代码详解
Jun 21 Javascript
为nuxt项目写一个面包屑cli工具实现自动生成页面与面包屑配置
Sep 29 Javascript
layui写后台表格思路和赋值用法详解
Nov 14 Javascript
JavaScript中this函数使用实例解析
Feb 21 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
双料怀旧--SHARP GF515的维护、修理和简单调试
2021/03/02 无线电
PHP验证码类代码( 最新修改,完全定制化! )
2010/12/02 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
2011/05/02 PHP
PHP分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
PHPCrawl爬虫库实现抓取酷狗歌单的方法示例
2017/12/21 PHP
起点页面传值js,有空研究学习下
2010/01/25 Javascript
javascript 事件查询综合 推荐收藏
2010/03/10 Javascript
理解Javascript_02_理解undefined和null
2010/10/11 Javascript
举例讲解Node.js中的Writable对象
2015/07/29 Javascript
通过XMLHttpRequest和jQuery实现ajax的几种方式
2015/08/28 Javascript
教你如何终止JQUERY的$.AJAX请求
2016/02/23 Javascript
Nodejs获取网络数据并生成Excel表格
2020/03/31 NodeJs
8 行 Node.js 代码实现代理服务器
2016/12/05 Javascript
轻松理解JavaScript之AJAX
2017/03/15 Javascript
详解vue-router2.0动态路由获取参数
2017/06/14 Javascript
js原生代码实现轮播图的实例讲解
2017/07/28 Javascript
NodeJs form-data格式传输文件的方法
2017/12/13 NodeJs
angular6.x中ngTemplateOutlet指令的使用示例
2018/08/09 Javascript
解决Angular4项目部署到服务器上刷新404的问题
2018/08/31 Javascript
简单了解常用的JavaScript 库
2020/07/16 Javascript
React Native登录之指纹登录篇的示例代码
2020/11/03 Javascript
[05:26]2014DOTA2西雅图国际邀请赛 iG战队巡礼
2014/07/07 DOTA
Python实现SVN的目录周期性备份实例
2015/07/17 Python
一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息
2018/04/17 Python
Python饼状图的绘制实例
2019/01/15 Python
对python3中, print横向输出的方法详解
2019/01/28 Python
python上selenium的弹框操作实现
2020/07/13 Python
详解h5页面在不同ios设备上的问题总结
2019/03/01 HTML / CSS
临床医学专业学生的自我评价分享
2013/11/21 职场文书
网络编辑岗位职责范本
2014/02/10 职场文书
班主任寄语2015
2015/02/26 职场文书
经理聘任证明
2015/03/02 职场文书
不同意离婚答辩状
2015/05/22 职场文书
导游词之河姆渡遗址博物馆
2019/10/10 职场文书
JS + HTML 罗盘式时钟的实现
2021/05/21 Javascript
AudioContext 实现音频可视化(web技术分享)
2022/02/24 Javascript