详解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 原型与继承说明
Jun 09 Javascript
jquery 简单应用示例总结
Aug 09 Javascript
jQuery中Ajax的load方法详解
Jan 14 Javascript
详解Vue 实例中的生命周期钩子
Mar 21 Javascript
javascript 初学教程及五子棋小程序的简单实现
Jul 04 Javascript
Angular2学习笔记之数据绑定的示例代码
Jan 03 Javascript
jQuery实现新闻播报滚动及淡入淡出效果示例
Mar 23 jQuery
jQuery实现的淡入淡出图片轮播效果示例
Aug 29 jQuery
解决vue A对象赋值给B对象,修改B属性会影响到A的问题
Sep 25 Javascript
Vue实现的父组件向子组件传值功能示例
Jan 19 Javascript
vue2.* element tabs tab-pane 动态加载组件操作
Jul 19 Javascript
Vue2.0搭建脚手架
Mar 13 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新手上路(五)
2006/10/09 PHP
深入PHP nl2br()格式化输出的详解
2013/06/05 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
2014/07/28 PHP
php中使用in_array() foreach array_search() 查找数组是否包含时的性能对比
2015/04/14 PHP
PHP getallheaders无法获取自定义头(headers)的问题
2016/03/23 PHP
深入解析PHP的Yii框架中的缓存功能
2016/03/29 PHP
php实现数组纵向转横向并过滤重复值的方法分析
2017/05/29 PHP
Laravel框架实现利用监听器进行sql语句记录功能
2018/06/06 PHP
PHP实现的CURL非阻塞调用类
2018/07/26 PHP
利用js对象弹出一个层
2008/03/26 Javascript
myFocus slide3D v1.1.0 使用方法与下载
2011/01/12 Javascript
ASP.NET MVC中EasyUI的datagrid跨域调用实现代码
2012/03/14 Javascript
JQuery获取样式中的background-color颜色值的问题
2013/08/20 Javascript
javascript使用定时函数实现跳转到某个页面
2013/12/25 Javascript
jQuery UI仿淘宝搜索下拉列表功能
2017/01/10 Javascript
Nodejs中使用captchapng模块生成图片验证码
2017/05/18 NodeJs
Nuxt.js实战详解
2018/01/18 Javascript
微信小程序Echarts覆盖正常组件问题解决
2019/07/13 Javascript
JS面向对象编程基础篇(二) 封装操作实例详解
2020/03/03 Javascript
django项目运行因中文而乱码报错的几种情况解决
2017/11/07 Python
Pandas标记删除重复记录的方法
2018/04/08 Python
python使用turtle库与random库绘制雪花
2018/06/22 Python
解决使用PyCharm时无法启动控制台的问题
2019/01/19 Python
python 实现让字典的value 成为列表
2019/12/16 Python
Python终端输出彩色字符方法详解
2020/02/11 Python
使用卷积神经网络(CNN)做人脸识别的示例代码
2020/03/27 Python
一个非常简单好用的Python图形界面库(PysimpleGUI)
2020/12/28 Python
HTML5 新旧语法标记对我们有什么好处
2012/12/13 HTML / CSS
HTML5中form如何关闭自动完成功能的方法
2018/07/02 HTML / CSS
巴西儿童时尚购物网站:Dinda
2019/08/14 全球购物
如何用Java判断一个文件或目录是否存在
2012/11/19 面试题
入党介绍人评语
2014/05/06 职场文书
一般纳税人申请报告
2015/05/18 职场文书
pytorch中的torch.nn.Conv2d()函数图文详解
2022/02/28 Python
python实现一个简单的贪吃蛇游戏附代码
2022/06/28 Python
MySQL事务的ACID特性以及并发问题方案
2022/07/15 MySQL