这篇文章主要介绍了 JS 小数运算出现多为小数问题的解决方法, 需要的朋友可以参考下
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言, 主要目的是为了解决服务器端语言, 比如 Perl, 遗留的速度问题, 为客户提供更流畅的浏览效果.
写在前面的话:
今天帮同事解决了一个问题, 就是小数相乘出现很多位小数的问题; 这个问题自己以前也遇到过, 现在特意来总结一下;
Number 类型:
Number 类型是 ECMAScript 中最常用和最令人关注的类型了; 这种类型使用 IEEE754 格式来表示整数和浮点数值 (浮点数值在某些语言中也被成为双精度数值), 为支持各种数据类型, ECMA-262 定义了不同的数值面量格式.
十进制:
var intNum=10; // 整数
八进制:
var octalNum1=070; // 八进制的 56
var octalNum2=079; // 无效的八进制数值 - 解析为 79
八进制字面量在严格模式下是无效的;
十六进制:
var hexNum1=0xA; //10
切记: 在进行运算的时候, 所有以八进制和十六进制表示的数值都最终被转换成十进制;
为什么操作小数会出现误差?
浮点数值的最高进度是 17 位小数, 但在进行运算的时候其精确度却远远不如整数; 整数在进行运算的时候都会转成 10 进制; 而 Java 和 JavaScript 中计算小数运算时, 都会先将十进制的小数换算到对应的二进制, 一部分小数并不能完整的换算为二进制, 这里就出现了第一次的误差. 待小数都换算为二进制后, 再进行二进制间的运算, 得到二进制结果. 然后再将二进制结果换算为十进制, 这里通常会出现第二次的误差.
所以 (0.1+0.2)!=03
解决方式:
程序代码
除法函数, 用来得到精确的除法结果
说明: javascript 的除法结果会有误差, 在两个浮点数相除的时候会比较明显. 这个函数返回较为精确的除法结果.
调用: accDiv(arg1,arg2)
返回值: arg1 除以 arg2 的精确结果
function accDiv(arg1, arg2) {
var t1 = 0,
t2 = 0,
r1, r2;
try {
t1 = arg1.toString().split(".")[1].length
} catch(e) {}
try {
t2 = arg2.toString().split(".")[1].length
} catch(e) {}
with(Math) {
r1 = Number(arg1.toString().replace(".", "")) r2 = Number(arg2.toString().replace(".", "")) return (r1 / r2) * pow(10, t2 - t1);
}
}
给 Number 类型增加一个 div 方法, 调用起来更加方便.
Number.prototype.div = function(arg) {
return accDiv(this, arg);
}
乘法函数, 用来得到精确的乘法结果
说明: javascript 的乘法结果会有误差, 在两个浮点数相乘的时候会比较明显. 这个函数返回较为精确的乘法结果.
调用: accMul(arg1,arg2)
返回值: arg1 乘以 arg2 的精确结果
function accMul(arg1, arg2) {
var m = 0,
s1 = arg1.toString(),
s2 = arg2.toString();
try {
m += s1.split(".")[1].length
} catch(e) {}
try {
m += s2.split(".")[1].length
} catch(e) {}
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
}
给 Number 类型增加一个 mul 方法, 调用起来更加方便.
Number.prototype.mul = function(arg) {
return accMul(arg, this);
}
加法函数, 用来得到精确的加法结果
说明: javascript 的加法结果会有误差, 在两个浮点数相加的时候会比较明显. 这个函数返回较为精确的加法结果.
调用: accAdd(arg1,arg2)
返回值: arg1 加上 arg2 的精确结果
function accAdd(arg1, arg2) {
var r1, r2, m;
try {
r1 = arg1.toString().split(".")[1].length
} catch(e) {
r1 = 0
}
try {
r2 = arg2.toString().split(".")[1].length
} catch(e) {
r2 = 0
}
m = Math.pow(10, Math.max(r1, r2)) return (arg1 * m + arg2 * m) / m
}
给 Number 类型增加一个 add 方法, 调用起来更加方便.
Number.prototype.add = function(arg) {
return accAdd(arg, this);
}
在你要用的地方包含这些函数, 然后调用它来计算就可以了.
比如你要计算: 7*0.8 , 则改成 (7).mul(8)
其它运算类似, 就可以得到比较精确的结果.
解决方式二:
比较常用的办法, toFixed(),toFixed() 方法可把 Number 四舍五入为指定小数位数的数字. 在我们计算的结果后面加上这个方法就 OK 了; 但是对精度会有一丝影响, 如果精度要求不高的话推荐使用;
来源: http://www.phperz.com/article/17/0228/265239.html