自定义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错误,甚至死循环.②.方 ...
随机推荐
- JAVA 二进制基础
主要内容 1.十进制二进制互转 2.二进制的位运算 3.JDK内置的进制转换 4.JAVA中的进制 十进制二进制互转 57 111001 二进制的位运算:优点:特定情况下,计算方便,被支持面广泛. ① ...
- js小知识点
1.setTimeout(function(num){ alert(num);},1000,123); 第三个参数为实参. 2.拼接字符串: document.body.innerHTML = '&l ...
- 初涉扫码登录:edusoho实现客户端扫码登录(简版)
一.项目简介及需求 edusoho是一套商业版的在线教育平台,项目本身基于symfony2框架开发,现在有一款自己的APP,要求在不多修改edusoho自身代码的基础上,实现客户端对PC端扫码登录.不 ...
- yii2 源码分析 model类分析 (五)
模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggreg ...
- 用Python发送邮件
文件:send.py # -*- coding:utf-8 -*- # ## 任兴测试用Python发送邮件 import os import sys import getopt import tim ...
- Linux常用命令手册
Linux常用命令手册 NO 分类 PS1 命令名 用法及参数 功能注解 对应章节 1 文件管理 # ls ls -a 列出当前目录下的所有文件,包括以.头的隐含文件 文件管理 # ls ls ...
- go入门
1.hello world 小程序 package main import "fmt" func main() { fmt.println("hello,世界" ...
- ubuntu终端常用命令及solarized配色(护眼)
ubuntu终端常用命令及solarized配色(护眼) ubuntu 终端 命令 1.常用命令 ctrl + l - 清屏 . cLear ctrl + c - 终止命令. ctrl + d ...
- sqlite不存在记录则插入数据
问题:如下图在Sqlite数据库中存在一张Student表,现需要向表中插入数据,如果不存在同名记录则插入,否则不进行插入操作. 解答:利用not exists语句,如下: insert into [ ...
- 关于c++栈溢出的问题
我自己定义了一个数据类型node,嵌套在另一个数据类型当中时候,用到了delete函数, 在我node的声明当中声明了几个指针 在我的析构函数中却调用了delet函数 结果程序结果是能跑出来 提示我栈 ...