自定义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错误,甚至死循环.②.方 ...
随机推荐
- BZOJ 3572: [Hnoi2014]世界树 [虚树 DP 倍增]
传送门 题意: 一棵树,多次询问,给出$m$个点,求有几个点到给定点最近 写了一晚上... 当然要建虚树了,但是怎么$DP$啊 大爷题解传送门 我们先求出到虚树上某个点最近的关键点 然后枚举所有的边$ ...
- opencv-python与c++ opencv中的一些区别和基础的知识
使用opencv-python一段时间了,因为之前没有大量接触过c++下的opencv,在网上看c++的一些程序想改成python遇到了不少坑,正好在这里总结一下. 1.opencv 中x,y,hei ...
- Flink入门使用
完全参考:Flink1.3QuickStart 启动本地运行 首先找一台安装了hadoop的linux. 将安装包解压,到bin目录启动local模式的脚本. tar -zxvf flink-1.3. ...
- 使用原生JS定位网页元素
约定:1.<meta name="viewport" content="width=device-width">这种标记简称"wdw&qu ...
- linux下boost的安装与编译
1.从boost官网下载boost库包: 2.然后解压到linux下的任意一个文件夹, 3.进入boost_1_57文件夹下,不同的boost版本会解压城不同的库文件夹, 4.执行././bootst ...
- TKCPP
volume one: http://book.huihoo.com/thinking-in-cpp-2nd-ed-vol-one/ volume2 : http://book.huihoo.com/ ...
- 打通MySQL的操作权限
打通MySQL的操作权限 前面已经总结了<XAMPP的配置与使用>,虽然可以直接通过GUI控制面板去启动MySQL服务,但是有些相关的操作则需要在Windows中的CMD命令窗口中去对My ...
- VC下防止反汇编的办法(1)
最近在看IDA的书,讲汇编语言的部分提到了一种防止递归向下汇编器逆向程序的方法 这里esp指向栈顶,也就是调用方最后入栈的返回地址.然而实际在VC2017里用内联汇编这么做是不行的,原因可以看看VC生 ...
- angular+require前端项目架构搭建
app //应用入口 directive //自定义指令 require-main //require的主配置文件 存放公共调用的js service //请求后端数据公有类 controllers ...
- C# Swagger 生成接口文档
一直听说Swagger是做Web API文档的好工具,这次手里暂时没什么事,类体验下它的强大之处.下面是使用Swashbuckle.net 给asp.net web API添加文档的简要步骤. 参考地 ...