1.变量加减法常见异常
在写html中的js时,进行变量的加减法经常会遇到的两种异常问题(表格中还包含了一般解决策略):
常见异常 | 举例 | 原因 | 一般解决策略 |
变量相加按照字符串方式相加 | 10+10=1010 | 系统在加减时有时默认将变量识别为字符串类型,而非数字类型 | parseFloat();<br>parseInt();<br>在变量运算第一步执行减零操作,如var sum=a-0+b; |
浮点数加减的结果有误差 | 1.63-0.63=0.99999732<br>(只是举个例子,真实的结果可能并非如此) | 浮点数设计误差的存在(任何系统的浮点数都无法避免该弊端) | parseInt();<br>toFixed();<br>Math.round(); |
2.一般解决策略可能存在的小问题
但是实际使用的过程中,会发现上述的一般解决策略在使用时,多多少少会遇到一些问题,尤其是将两种异常放在一起的时候,都不是那么完美:
- parseFloat(): 将任意可识别的变量转化为数字类型,方法本身没有什么问题,但在加减法的过程中,往往会出现第二种异常,需要其他方法的协同.
- parseInt(): 将任意可识别的变量转化为整数的数字类型,与parseFloat()相似,但==不建议使用==,因为在分析非整型的变量时会默认使用去尾法,考虑到第二种异常的存在,即使计算中的所有变量都是整数,最后可能也不能得到准确的值.
- 变量运算第一步执行减零操作: 这种策略我使用的较少,唯一一次使用的时候正好碰到了多个变量的加减法,发现还是出现了第一种异常,所以个人是==不太推荐==的.
- toFixed(): 该函数的本义是将数字类型转化为理想位数的字符串,在使用上有两个限制,一是执行变量必须确保是数字类型,否则会报错;二是它转化为字符串类型的数字显示时,并不完全是按照四舍五入的规则进行的.这点用toFixed()比较多的人应该深有感触,当执行变量的舍入首位为5时,该函数会进行各种各样奇怪的舍入,好在当舍入首位非5的情况下,还是严格按照四舍五入规则的.
- Math.round(): 标准的四舍五入方法,如果硬要说缺点,那就是只能将数字四舍五入到整数上,这确实是个限制.
3.简单而严谨的实现变量加减法--封装函数
通过第二部分我们得知目前常用的解决策略,多多少少都一些缺点或不足,似乎没有一个非常严谨而又简单的方法来实现加减法.
基于此,我写了一个封装函数来实现这个功能:
(由于没有很好的浮点数的四舍五入方法,此处使用的是先将所有变量乘以10^n^,变为整数再进行加减操作,最后除以10^n^)
/** * 数据处理-准确(准确程度视位数而定)的加减法 * @param arrNum 加减数的数组 * @param isNum (选填)返回结果是否为数字,默认返回字符串 * @param digits (选填)精确位数,默认为2位 * @returns */ function sum_pack(arrNum,isNum,digits){ digits=digits||2; isNum=isNum||false; var multi=Math.pow(10,digits); var intSum=0; for(var i in arrNum){ var num=arrNum[i]; if(num!=''&&!isNaN(num)){ var fltNum=parseFloat(num); //此处也可考虑将四舍五入放在加减后进行,视业务需求而定 var intNum=Math.round(fltNum*multi); intSum+=intNum; }else if(isNaN(num)){ console.log('can not parse : '+num); } } var fltSum=intSum/multi; if(isNum){ return fltSum; }else{ return fltSum.toFixed(digits); } }
用法参考如下:
var s='5.678'; var arrNum=[1,'2.3',-4,-s];//-s在js中会自动取相反数,负数亦然 var sum1=sum_pack(arrNum); var sum2=sum_pack(arrNum,true); var sum3=sum_pack(arrNum,true,3); console.log(sum1);//print:-6.4,字符串类型 console.log(sum2);//print:-6.4,数字类型 console.log(sum3);//print:-6.38,数字类型