一、浮点型数字的精度
- 问题:JS中的数据类型即Number,这种类型使用IEEE754格式来表示整数和浮点数值,用 IEEE 754(二进制浮点数算术标准) 标准的64 位双精度浮点数数做运算的时候经常有一些问题。
- 组成:1位符号位, s 表示 ,0表示正数,1表示负数;11位– 储存指数部分 e 表示 ;52位–储存小数部分(即有效数字)f 表示。
- 原因:浮点数用二进制表达时是无穷的,因浮点数小数位的限制而截断的二进制数字,再转换为十进制,例如0.1+0.2就成了 0.30000000000000004。
//浮点数的加法
function accAdd(arg1,arg2){
var r1,r2,m,c;
try{
r1 = arg1.toString().split(".")[1].length;
}catch(e){
r1 = 0;
}
try{
r2 = arg2.toString().split(".")[1].length;
}catch(e){
r2 = 0
}
c = Math.abs(r1-r2);
m = Math.pow(10,Math.max(r1,r2));
if(c>0){
var cm = Math.pow(10,c);
if(r1>r2){
arg1 = Number(arg1.toString().replace(".",""));
arg2 = Number(arg2.toString().replace(".",""))*cm;
}else{
arg1 = Number(arg1.toString().replace(".",""))*cm;
arg2 = Number(arg2.toString().replace(".",""));
}
}else{
arg1 = Number(arg1.toString().replace(".",""));
arg2 = Number(arg2.toString().replace(".",""));
}
return (arg1+arg2)/m;
}
//浮点数的减法
function accSub(arg1,arg2){
var r1,r2,m,n;
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));
// n = (r1>= r2) ? r1 :r2;
// return ((arg1*m-arg2*m) / m ).toFixed(n);
c = Math.abs(r1-r2);
m = Math.pow(10,Math.max(r1,r2));
if(c>0){
var cm = Math.pow(10,c);
if(r1>r2){
arg1 = Number(arg1.toString().replace(".",""));
arg2 = Number(arg2.toString().replace(".",""))*cm;
}else{
arg1 = Number(arg1.toString().replace(".",""))*cm;
arg2 = Number(arg2.toString().replace(".",""));
}
}else{
arg1 = Number(arg1.toString().replace(".",""));
arg2 = Number(arg2.toString().replace(".",""));
}
return (arg1-arg2)/m;
}
二、整数精度问题
- JavaScript 中 Number类型统一按浮点数处理,整数是按最大54位来算最大(Number.MIN_SAFE_INTEGER|Number.MAX_SAFE_INTEGER),超出了这个范围就会存在舍去位数,精度计算不准的问题。
- 大数运算
三、其他成熟的库
精度要求比较高的时候一般是后台处理,如果前端需要一般也有相应的类库处理。
1. 二进制浮点数算术标准 https://zh.wikipedia.org/wiki/IEEE_754
2. mathjs http://mathjs.org/
3. decimal http://mikemcl.github.io/decimal.js/
4. big http://mikemcl.github.io/big.js