自定义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错误,甚至死循环.②.方 ...
随机推荐
- POJ 2065 SETI [高斯消元同余]
题意自己看,反正是裸题... 普通高斯消元全换成模意义下行了 模模模! #include <iostream> #include <cstdio> #include <c ...
- Nginx设置身份验证
在某些情况下,需要对某些内容的访问进行限制,在Nginx中也提供了这样的限制措施,以下是几种常见的限制措施: 1.访问身份验证 在Nginx的插件模块中有一个模块ngx_http_auth_basic ...
- 织梦去除版权中的Power by DedeCms
找到文件 \include\dedesql.class.php 注释或删除下面代码,大概在588行 $arrs1 = array(0x63,0x66,0x67,0x5f,0x70,0x6f,0x77, ...
- 【JavaWeb】客户关系管理系统
前言 为了巩固开发的流程,我们再拿一个客户关系管理系统来练手...! 成果图 我们完成的就是下面的项目! 搭建配置环境 配置Tomcat 导入开发包 建立开发用到的程序包 在数据库创建相对应的表 CR ...
- angular+require前端项目架构搭建
app //应用入口 directive //自定义指令 require-main //require的主配置文件 存放公共调用的js service //请求后端数据公有类 controllers ...
- 批量修改git仓库地址脚本
前言 公司的代码都存放在自己搭建的gitlab上面.之前由于老板升级gitlab.导致下面有个叫做"api"的groups无法访问.通过无所不能的谷歌才知道.在gitlab在某 ...
- 由select引发的思考
一.前言 网络编程里一个经典的问题,selec,poll和epoll的区别?这个问题刚学习编程时就接触了,当时看了材料很不明白,许多概念和思想没有体会,现在在这个阶段,再重新回头看这个问题,有一种豁然 ...
- Shiro登录成功之后跳到指定URL
通常我们使用shiro,登录之后就会跳到我们上一次访问的URL,如果我们是直接访问登录页面的话,shiro就会根据我们配置的successUrl去重定向,如果我们没有配置successUrl的话,那么 ...
- Flask Ansible自动化平台搭建(持续更新)
一:简介 使用Ansible + Flask + Celery搭建web平台. 目录结构 . ├── ansible_api │ ├── ansible_playbook_inventory.py ...
- Effective Java 第三版——34. 使用枚举类型替代整型常量
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...