方案来自网络,实现简单,便于做加减乘除使用,由于项目临时要用记录下

如需要更加复杂的计算类库,可以考虑 math.js等知名类库

/**
* floatTool 包含加减乘除四个方法,能确保浮点数运算不丢失精度
*
* 我们知道计算机编程语言里浮点数计算会存在精度丢失问题(或称舍入误差),其根本原因是二进制和实现位数限制有些数无法有限表示
* 以下是十进制小数对应的二进制表示
* 0.1 >> 0.0001 1001 1001 1001…(1001无限循环)
* 0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
* 计算机里每种数据类型的存储是一个有限宽度,比如 JavaScript 使用 64 位存储数字类型,因此超出的会舍去。舍去的部分就是精度丢失的部分。
*
* ** method **
* add / subtract / multiply /divide
*
* ** explame **
* 0.1 + 0.2 == 0.30000000000000004 (多了 0.00000000000004)
* 0.2 + 0.4 == 0.6000000000000001 (多了 0.0000000000001)
* 19.9 * 100 == 1989.9999999999998 (少了 0.0000000000002)
*
* floatObj.add(0.1, 0.2) >> 0.3
* floatObj.multiply(19.9, 100) >> 1990
*
*/
var floatTool = function() { /*
* 判断obj是否为一个整数
*/
function isInteger(obj) {
return Math.floor(obj) === obj
} /*
* 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
* @param floatNum {number} 小数
* @return {object}
* {times:100, num: 314}
*/
function toInteger(floatNum) {
var ret = {times: 1, num: 0}
if (isInteger(floatNum)) {
ret.num = floatNum
return ret
}
var strfi = floatNum + ''
var dotPos = strfi.indexOf('.')
var len = strfi.substr(dotPos+1).length
var times = Math.pow(10, len)
var intNum = parseInt(floatNum * times + 0.5, 10)
ret.times = times
ret.num = intNum
return ret
} /*
* 核心方法,实现加减乘除运算,确保不丢失精度
* 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
*
* @param a {number} 运算数1
* @param b {number} 运算数2
* @param digits {number} 精度,保留的小数点数,比如 2, 即保留为两位小数
* @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
*
*/
function operation(a, b, op) {
var o1 = toInteger(a)
var o2 = toInteger(b)
var n1 = o1.num
var n2 = o2.num
var t1 = o1.times
var t2 = o2.times
var max = t1 > t2 ? t1 : t2
var result = null
switch (op) {
case 'add':
if (t1 === t2) { // 两个小数位数相同
result = n1 + n2
} else if (t1 > t2) { // o1 小数位 大于 o2
result = n1 + n2 * (t1 / t2)
} else { // o1 小数位 小于 o2
result = n1 * (t2 / t1) + n2
}
return result / max
case 'subtract':
if (t1 === t2) {
result = n1 - n2
} else if (t1 > t2) {
result = n1 - n2 * (t1 / t2)
} else {
result = n1 * (t2 / t1) - n2
}
return result / max
case 'multiply':
result = (n1 * n2) / (t1 * t2)
return result
case 'divide':
return result = function() {
var r1 = n1 / n2
var r2 = t2 / t1
return operation(r1, r2, 'multiply')
}()
}
} // 加减乘除的四个接口
function add(a, b) {
return operation(a, b, 'add')
}
function subtract(a, b) {
return operation(a, b, 'subtract')
}
function multiply(a, b) {
return operation(a, b, 'multiply')
}
function divide(a, b) {
return operation(a, b, 'divide')
} // exports
return {
add: add,
subtract: subtract,
multiply: multiply,
divide: divide
}
}();

使用方法:

floatTool.add(a,b);//相加
floatTool.subtract(a,b);//相减
floatTool.multiply(a,b);//相乘
floatTool.divide(a,b);//相除

javascript在计算浮点数(小数)不准确,解决方案的更多相关文章

  1. 解决JavaScript浮点数(小数) 运算出现Bug的方法

    解决JS浮点数(小数) 运算出现Bug的方法例如37.2 * 5.5 = 206.08 就直接用JS算了一个结果为: 204.60000000000002 怎么会这样, 两个只有一位小数的数字相乘, ...

  2. 计算价格, java中浮点数精度丢失的解决方案

    计算价格, java中浮点数精度丢失的解决方案

  3. javascript中的浮点数运算

    解释一下下面代码的输出 console.log(0.1 + 0.2); //0.30000000000000004 console.log(0.1 + 0.2 == 0.3); //false Jav ...

  4. javascript保留两位小数

      原文地址http://blog.csdn.net/he20101020/article/details/8503308   <script type="text/javascrip ...

  5. js(javascript)取float型小数点后两位数的方法

    以下我们将为大家介绍 JavaScript 保留两位小数的实现方法:四舍五入以下处理结果会四舍五入: ? 1 2 var num =2.446242342; num = num.toFixed(2); ...

  6. [学习笔记]Javascript采用二进制浮点数和四舍五入的错误

    1.样例 var a = .3 - .2 //0.09999999999999998 var b = .2 - .1 //0.1 a == b //false 出现这样的原因在于 1.Javascri ...

  7. JavaScript 保留两位小数

    以下我们将为大家介绍 JavaScript 保留两位小数的实现方法: 四舍五入 以下处理结果会四舍五入: var num =2.446242342; num = num.toFixed(2); // ...

  8. Javascript时间差计算函数代码实例

    Javascript时间差计算函数代码实例 <script language="javascript"> Date.prototype.dateDiff = funct ...

  9. 闰年计算——JavaScript 语言计算

    ㈠闰年是如何来的? 闰年(Leap Year)是为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差而设立的.补上时间差的年份为闰年. ㈡什么是闰年? 凡阳历中有闰日(二月为二十九日)的年, ...

随机推荐

  1. MT【246】方程根$\backsim$图像交点

    已知函数$f(x)=x^2+x-2$,若$g(x)=|f(x)|-f(x)-2mx-2m^2$ 有三个不同的零点,则$m$的取值范围_____ 分析:等价于$h(x)=|f(x)|-f(x),t(x) ...

  2. 【POJ1037】A decorative fence(DP)

    BUPT2017 wintertraining(15) #6C 题意 给长度n的数列,1,2,..,n,按依次递增递减排序,求字典序第k小的排列. 题解 dp. up[i][j]表示长度为j,以第i小 ...

  3. 【正睿oi省选十连测】第一场

    四小时写了两个暴力??自闭 [原来这就是神仙们的分量Orz rank 56/75 可以说是无比垃圾了 下周目标:进步十名?[大雾 T1 题意:有n个点的图 点有点权Ai 也有点权Bi = A_1 + ...

  4. angularJS 路由加载js controller 未定义 解决方案

    说明 本文主要说明,在angularJS框架使用中,angularJS 路由加载js controller 未定义 解决方案. 路由 $routeProvider 异步加载js 路由的基本用法,请查看 ...

  5. CodeForces Global Round 1

    CodeForces Global Round 1 CF新的比赛呢(虽然没啥区别)!这种报名的人多的比赛涨分是真的快.... 所以就写下题解吧. A. Parity 太简单了,随便模拟一下就完了. B ...

  6. stm32使用rt-thread在文件《stm32f1xx_hal.h》中头文件包含顺序引出的错误

    @2019-01-24 [小记] 在学习 rt-thread BSP制作过程中,发现文件<stm32f1xx_hal.h>中 Env工具生成的原始顺序 1. #include " ...

  7. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  8. iptables(2)

    MASQUERADE同样是做源地址转换,只不过防火墙会根据该策略自动查找可用的公网IP地址,适应变化的情况•若接口使用ppp+,表示匹配ppp0.ppp1……中任意可用的拨号连接•若需要演示操作,可以 ...

  9. [HAOI2012]道路(最短路DAG上计数)

    C国有n座城市,城市之间通过m条[b]单向[/b]道路连接.一条路径被称为最短路,当且仅当不存在从它的起点到终点的另外一条路径总长度比它小.两条最短路不同,当且仅当它们包含的道路序列不同.我们需要对每 ...

  10. Electron一学习资源收集和练习demo

    1.近日为了做项目查资料学习electron,简直头都要炸了,就官方的electron-quick-start的例子进行了基本的练习之后,不断的查资料终于发现一些有用的demo来看源代码学习,一遍看代 ...