自定义JS乘法运算误差解决!
在实际开发中遇到这样一个乘法公式:数量*单价=总价
像这样的浮点数列子:200*8.2,JS算出的结果是:

像这种浮点数的乘法计算就会有误差,我们需要得到准确的值应该是:1640,与我们后台C#计算结果要一致。
这里我们采用两种方式来解决。
1:乘数和被乘数同时扩大10000倍。因为金额的最小单位也就是厘。然后结果在除以100000000,公式是:(2000000*82000)/100000000
这种方式如果小数位要求越高,也还是有误差的,下面再说。
2:自定义乘法,这种方式利用小学的计算公式,拆分计算,目的是避免float*float,而是使用int*float ,公式是:200*8.2 拆分就是:(200*8+200*0.2)+(0*8+0*0.2)
具体实现代码如下:
/**
* 将小数拆分为整数+小数形式返回数组
* @method
* @param {String} 字符串数字
* @return {Array} 返回数组 数组下表[0]部分为是否成功,数组[1]部分为整数,数组[2]为小数
*/
function getDecimal(num) {
var numArray = new Array();
// 将输入的内容转为float类型(如果是小数为了保留小数部分)
if (checkNumber(num)) {
var isFloat = parseFloat(num); if (isFloat === 0) {
numArray[0] = true;
numArray[1] = parseFloat("0.0");// 整数部分
numArray[2] = parseFloat("0.0");
} else {
// 是数字类型
numArray[0] = true;
//判断是否有小数
if (isFloat.toString().indexOf(".") < 0) {
numArray[1] = isFloat;// 整数部分
numArray[2] = parseFloat("0.0");
} else {
var numArr = isFloat.toString().split(".");
numArray[1] = parseInt(numArr[0]);// 整数部分
numArray[2] = parseFloat('0.' + numArr[1]);// 小数部分
}
}
} else {
numArray[0] = false;
}
return numArray;
} /**
* 解决小数精度问题
* @param {*数字 } a
* @param {*数字 } b
* @param {*符号 } sign
* fixedFloat(0.3, 0.2, '-')
* 参考:https://my.oschina.net/cjlice/blog/1616682
*/ function fixedFloat(a, b, sign) {
function handle(x) {
var y = String(x);
var p = y.lastIndexOf('.');
if (p === -1) {
return [y, 0];
} else {
return [y.replace('.', ''), y.length - p - 1];
}
}
// v 操作数1, w 操作数2, s 操作符, t 精度
function operate(v, w, s, t) {
switch (s) {
case '+':
return (v + w) / t;
case '-':
return (v - w) / t;
case '*':
return (v * w) / (t * t);
case '/':
return (v / w);
}
} var c = handle(a);
var d = handle(b);
var k = 0; if (c[1] === 0 && d[1] === 0) {
return operate(+c[0], +d[0], sign, 1);
} else {
k = Math.pow(10, Math.max(c[1], d[1]));
if (c[1] !== d[1]) {
if (c[1] > d[1]) {
d[0] += padding0(c[1] - d[1]);
} else {
c[0] += padding0(d[1] - c[1]);
}
}
return operate(+c[0], +d[0], sign, k);
}
} // 补0
function padding0(p) {
var z = '';
while (p--) {
z += '0';
}
return z;
} // 加
function plus(a, b) {
return fixedFloat(a, b, '+');
}
// 减
function minus(a, b) {
return fixedFloat(a, b, '-');
}
// 乘
function multiply(a, b) {
return fixedFloat(a, b, '*');
}
// 除
function division(a, b) {
return fixedFloat(a, b, '/');
} /**
* 自定义加法
* @method
* @param {String} 字符串
* @param {String} 字符串
* @return {number} 返回计算结果
*/
function addition(numOne, numTwo) {
return plus(numOne, numTwo);
} /**
* 自定义乘法
* @method
* @param {String} 字符串
* @param {String} 字符串
* @return {number} 返回计算结果
*/
function multiplication(numOne, numTwo) {
return multiply(numOne, numTwo);
}; /**
* 判断输入是否是数字(包含小数正负)
* @method
* @param {String} 字符串
* @return {true/false} 返回true/false
*/
function checkNumber(theObj) {
var reg = /^(\\-|\+)?\d+(\.\d+)?$/;
if (reg.test(theObj)) {
return true;
}
return false;
}
自定义JS乘法运算误差解决!的更多相关文章
- 两个js冲突怎么解决?试试这四个方法
两个js冲突很让前端头疼,虽然jquery是通用的,但调用不同经常会出问题.jQuery是目前流行的JS封装包,简化了很多复杂的JS程序,JQuery讲浏览器DOM树定义为$,通过$来获取各个子节点. ...
- ie不兼容的几个js问题及解决办法
1.table问题 在动态新增tr或者td时,createElement()一般用appendChild();都不生效,解决办法是用新增tbody,如 var table=document.creat ...
- 示例篇-购物车的简单示例和自定义JS
简介: 支持平台: Android4.0,iOS7.0,Windows 10, Windows 10 mobile 说明:主要是演示listview所在的ui和模板cell所在的ui之间数据的交互,点 ...
- mvc正则@符号js报错解决办法
很简单在@前面再加个@就行了,也可以以引进js 的形式解决!
- 常见JS(JavaScript)冲突解决方法
1.一般JS冲突解决办法 a.最容易出现的就是js的命名冲突 ①.变量名冲突 变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScr ...
- IE 不兼容的几个js问题及解决方法
IE 不兼容的几个js问题及解决方法 1 Table的问题 在动态新增tr或者td时,createElecment() 一般用appendChild();都不生效,解决办法是用新增tbody, 如 ...
- IE 不兼容的几个js问题及解决方法1
IE 不兼容的几个js问题及解决方法 1 Table的问题 在动态新增tr或者td时,createElecment() 一般用appendChild();都不生效,解决办法是用新增tbody, 如 ...
- 利用servlet做转发,实现js跨域解决同源问题
做前端开发,避免不了跨域这个问题,跨域具体什么概念,不赘述,博客里太多.简单说下,我们用js发请求,不管post还是get,如果发请求的对象和当前web页面不在同一域名下,浏览器的同源策略会限制发请求 ...
- js冲突怎么解决
a.最容易出现的就是js的命名冲突①.变量名冲突变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScript错误,甚至死循环.②.方 ...
随机推荐
- CF 375D. Tree and Queries加强版!!!【dfs序分块 大小分类讨论】
传送门 题意: 一棵树,询问一个子树内出现次数$\ge k$的颜色有几种,Candy?这个沙茶自带强制在线 吐槽: 本来一道可以离散的莫队我非要强制在线用分块做:上午就开始写了然后发现思路错了...: ...
- 使用Python的requests库进行接口测试——session对象的妙用
from:http://blog.csdn.net/liuchunming033/article/details/48131051 在进行接口测试的时候,我们会调用多个接口发出多个请求,在这些请求中有 ...
- pandas读取各类sql数据源
大数据分析中,我们经常需要使用pandas工具读取各类数据源并将结果保存到数据库中. 本文总结了一些读取和写入常用数据库数据的一些方法,包括mysql,oracle,impala等. 其中读取数据库数 ...
- Install Centrifugo and quick start
Install Centrifugo and quick start Go is a perfect language - it gives developers an opportunity to ...
- ★Linux桌面系统技巧(作为客户端)
[安装chrome浏览器]* 下载(已下载完成):32位:wget https://dl.google.com/linux/direct/google-chrome-stable_current_i3 ...
- 利用while语句,条件为输入的字符不为'\n'.
题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. 1.程序分析:利用while语句,条件为输入的字符不为'\n'. 一个很简单的问题,其实换种方式就能完成,但是我就想怎么着才能 ...
- unbuntu 系统登录华南师范大学校园网的方法
最近刚装了unbuntu 系统,刚开始网络连接遇到了点小问题,原来是校园网不知道怎么认证,于是向好基友请教了下,得出快捷的方法如下: 下载学校网络的认证客户端,记住位置,一般都是默认下载地址是 Dow ...
- maven指定部署的服务器类型
<!-- 指定部署的服务器类型 --> <plugins> <!-- <plugin> <groupId>org.apache.tomcat.ma ...
- Android Stdio 中的Rendering Problems Android N requires the IDE to be running with Java 1.8 or later Install a supported JDK解决办法
出现如下图所示的错误 解决办法为: 然后在里面输入SDK 下载 下载APILevel为23版本的SDK 换成23版本的SDK 完美解决问题
- 编程中&和&&的区别
逻辑电路中用&: 与门电路,全真为真,有假为假. 编程中:&表示取地址符(C)和 按位与(非bool类型时,转换成二进制,按位与运算). &&表示逻辑与运算,& ...