前言小学数学老师教我们0.1+0.2=0.3,但是为什么我们浏览器控制台输出的是0.30000000000000004?除了加法的奇怪现象外,带小数点的减法、乘法和除法的计算也会出现意想不到的结果log(0.3/0.1)//2.9999999999999996之所以我们都知道计算机是用二进制计算的,也就是0和1。以0.1+0.2为例,0.1表示为0.0001100110011001...,0.2表示为0.0011001100110011...而在二进制中,1+1=10,所以0.1+0.2=0.0100110011001100...换算成十进制,大约表示为0.300000000000000004。结论很简单,浮点数转换成二进制就丢失了精度,所以二进制计算完成后,精度就丢失了。转换回十进制时,可能与理论结果不同。对于浮点数的四种算术运算,很多编程语言都会存在理论值和实际值不一样的问题。比如在Java中也会出现类似的问题,但是在Java中可以使用java.math.BigDecimal类来避免这种情况。但是,JS是一种弱类型语言。作者BrendanEich表示,他在10天内开发了JS语言。浮点运算没有很好的处理方法,那么在日常开发的前端项目中如何解决呢?解决方法很简单。使用toFixed()<不推荐>控制小数位数。如果为空,则补0,返回一个字符串>0.123.toFixed(2)//'0.12'缺点:在不同的浏览器中获取的值可能不同,有些数可能得不到预期的结果,并且不执行严格舍入//在chrome控制台中>1.014.toFixed(2)//'1.01'>1.215.toFixed(2)//'1.22'>1.105.toFixed(2)//'1.10'>1.115.toFixed(2)//'1.11'乘以10的n次方将要计算的数乘以10的n次方,让数值变成整数,然后除以10的n次方后计算,这样就不会损失浮点精度>(0.1*10+0.2*10)/10//0.3我们可以将其封装为AfunctionmathFloat=function(float,digit){constmath=Math.战俘(10,数字);returnparseInt(float*math,10)/math;}mathFloat(0.1+0.2,3)//0.3Cons:JS中的存储是用8字节双精度浮点型表示的,所以不能准确记录所有数字.Number.MAX_SAFE_INTEGER取值范围为9007199254740991,Number.MIN_SAFE_INTEGER取值范围为-9007199254740991。如果超过这个范围,JS就无法表示了。虽然范围有限,但该值一般足以实现更完整的加法函数mathPlus(arg1,arg2){letr1,r2,m;尝试{r1=arg1.toString().split(".")[1].length;//获取小数点后字符的长度}catch(error){r1=0;//为整数,将0赋值给r1}try{r2=arg2.toString().split(".")[1].length;}catch(error){r2=0;}m=Math.pow(10,Math.max(r1,r2));//确保所有参数都是整数return(arg1*m+arg2*m)/m;}>mathPlus(0.1,0.2);//0.3>mathPlus(1,2);//3减法函数mathSubtract(arg1,arg2){letr1,r2,m;try{r1=arg1.toString().split(".")[1].length;}catch(error){r1=0;}try{r2=arg2.toString().split(".")[1].length;}catch(error){r2=0;}m=Math.pow(10,Math.max(r1,r2));返回((arg1*m-arg2*m)/m);}>mathSubtract(0.3,0.1);//0.2>mathSubtract(3,1);//2乘法函数mathMultiply(arg1,arg2){letm=0;lets1=arg1.toString();lets2=arg2.toString();try{m+=s1.split('.')[1].length;//小数相乘,小数点后加数}catch(e){}try{m+=s2.split('.')[1].length;}catch(e){}返回((数(s1.replace('.',''))*Number(s2.replace('.','')))/Math.pow(10,m));}>mathMultiply(0.1,0.2);//0.02>数学乘法(1,2);//除以2functionmathDivide(arg1,arg2){letm1=0;让m2=0;让n1=0;让n2=0;try{m1=arg1.toString().split('.')[1].length;}catch(e){}try{m2=arg2.toString().split('.')[1].length;}catch(e){}n1=Number(arg1.toString().replace('.',''));n2=Number(arg2.toString().replace('.',''));/***将除法转换为乘法*乘法取小数点后的差值*/returnmathMultiply(n1/n2,Math.pow(10,m2-m1));}//>0.2/0.03=>6.666666666666667>mathDivide(0.2,0.03);//6.66666666666665>mathDivide(0.3,0.1);//3>数学除法(3,1);//3引入第三方库站在前人的肩膀上,可以更快的前进下面这些成熟的库封装了很多有用的功能,虽然有些功能可能永远用不到。Math.js简介:功能强大,内置函数多,体积大..star:12.2k+decimal.js简介:支持三角函数等,支持非整数幂Github地址:https://github.com/MikeMcl/de...star:4.8k+big.js介绍:卷6k,提供CDNGithub地址:https://github.com/MikeMcl/bi...star:3.9k+number-精度介绍:很小,只有1k左右Github地址:https://github.com/nefe/numbe...star:3.4k+
