当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用1来表示“开”,0来表示“关”。
js精准计算
varnumA=0.1;
varnumB=0.2;
alert(numA+numB);
0.1+0.2=0.30000000000000004。
计算精度误差问题(和二进制相关)。
对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在C++/C#/java这些语言中已经封装好了方法来避免精度的问题,而Javascript是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。
我们先把0.1和0.2转换成二进制看看:
0.1=>0.0001100110011001…(无限循环)
0.2=>0.0011001100110011…(无限循环)
双精度浮点数的小数部分最多支持52位,所以两者相加之后得到这么一串0.0100110011001100110011001100110011001100110011001100因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了0.30000000000000004。
如何解决呢?
首先将数乘以10的幂次方去掉小数位得到可以转化二进制的整数,计算之后再还原。
functionaccDiv(arg1,arg2){
vart1=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)*Math.pow(10,t2-t1);
}
}
functionaccAdd(arg1,arg2){
varr1,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){
varcm=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;
}
functionaccMul(arg1,arg2){
varm=0,s1=arg1.toString(),s2=arg2.toString();
try{
m+=s1.split(".")[1].length;
}
catch(e){
}
try{
m+=s2.split(".")[1].length;
}
catch(e){
}
returnNumber(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
}
二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。