在实际开发中遇到这样一个乘法公式:数量*单价=总价

像这样的浮点数列子: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乘法运算误差解决!的更多相关文章

  1. 两个js冲突怎么解决?试试这四个方法

    两个js冲突很让前端头疼,虽然jquery是通用的,但调用不同经常会出问题.jQuery是目前流行的JS封装包,简化了很多复杂的JS程序,JQuery讲浏览器DOM树定义为$,通过$来获取各个子节点. ...

  2. ie不兼容的几个js问题及解决办法

    1.table问题 在动态新增tr或者td时,createElement()一般用appendChild();都不生效,解决办法是用新增tbody,如 var table=document.creat ...

  3. 示例篇-购物车的简单示例和自定义JS

    简介: 支持平台: Android4.0,iOS7.0,Windows 10, Windows 10 mobile 说明:主要是演示listview所在的ui和模板cell所在的ui之间数据的交互,点 ...

  4. mvc正则@符号js报错解决办法

    很简单在@前面再加个@就行了,也可以以引进js 的形式解决!

  5. 常见JS(JavaScript)冲突解决方法

    1.一般JS冲突解决办法 a.最容易出现的就是js的命名冲突 ①.变量名冲突 变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScr ...

  6. IE 不兼容的几个js问题及解决方法

    IE 不兼容的几个js问题及解决方法 1 Table的问题   在动态新增tr或者td时,createElecment() 一般用appendChild();都不生效,解决办法是用新增tbody, 如 ...

  7. IE 不兼容的几个js问题及解决方法1

    IE 不兼容的几个js问题及解决方法 1 Table的问题   在动态新增tr或者td时,createElecment() 一般用appendChild();都不生效,解决办法是用新增tbody, 如 ...

  8. 利用servlet做转发,实现js跨域解决同源问题

    做前端开发,避免不了跨域这个问题,跨域具体什么概念,不赘述,博客里太多.简单说下,我们用js发请求,不管post还是get,如果发请求的对象和当前web页面不在同一域名下,浏览器的同源策略会限制发请求 ...

  9. js冲突怎么解决

    a.最容易出现的就是js的命名冲突①.变量名冲突变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScript错误,甚至死循环.②.方 ...

随机推荐

  1. CF 208E. Blood Cousins [dsu on tree 倍增]

    题意:给出一个森林,求和一个点有相同k级祖先的点有多少 倍增求父亲然后和上题一样还不用哈希了... #include <iostream> #include <cstdio> ...

  2. BZOJ 1370: [Baltic2003]Gang团伙 [并查集 拆点 | 种类并查集WA]

    题意: 朋友的朋友是朋友,敌人的敌人是朋友:朋友形成团伙,求最多有多少团伙 种类并查集WA了一节课,原因是,只有那两种关系才成立,诸如朋友的敌人是朋友之类的都不成立! 所以拆点做吧 #include ...

  3. [快速傅立叶变换&快速傅里叶变换]【旧 手写笔记】

    $FFT$好美啊 参考资料: 1.算法导论 2.Miskcoo 3.Menci 4.虚数的意义-阮一峰 简单说一下,具体在下面的图片 实现: 可以用$complex$也可以手写 和计算几何差不多 注意 ...

  4. 【SSH框架】之Spring系列(一)

    微信公众号:compassblog 欢迎关注.转发,互相学习,共同进步! 有任何问题,请后台留言联系! 1.前言 前面更新过几篇关于 Struts2 框架和 Hibernate 框架的文章,但鉴于这两 ...

  5. IDEA的优质使用博客资源

    intelliJ idea 使用技巧&方法 IntelliJ IDEA 常用设置讲解 IntelliJ IDEA 详细图解最常用的配置 ,适合刚刚用的新人. IntelliJ IDEA 常见文 ...

  6. Apollo学习

    Apollo的配置 参考: Apollo 配置详细步骤(Windows环境) MQTT再学习 -- 搭建MQTT服务器及测试 分布式部署指南 Java客户端使用指南

  7. MySQL创建用户与授权

    一. 创建用户 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username:你将创建的用户名 host:指定该用户 ...

  8. mysql 查找某个表在哪个库

    SELECT table_schema FROM information_schema.TABLES WHERE table_name = '表名';

  9. 利用Jsonp实现跨域请求,spring MVC+JQuery

    1 什么是Jsonp? JSONP(JSON with Padding)是数据格式JSON的一种"使用模式",可以让网页从别的网域要数据.另一个解决这个问题的新方法是跨来源资源共享 ...

  10. sql server两个时间段内,求出周末的量

    公司有个表记录了出差(加班)的初始时间和截止时间,现在要计算出加班时间,之前的设计并没有考虑到这部分,因此本人通过sql重新计算周末数 表formmain starttime endtime 使用游标 ...