js小数运算异常处理
异常:
小数运算相乘出现无限循环异常
let result
result = 3*2.8;
console.log('result:',result);
异常原因:
JavaScript 里的数字是采用 IEEE 754 标准的 64 位双精度浮点数。该规范定义了浮点数的格式,对于64位的浮点数在内存中的表示,最高的1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体:
第0位:符号位, s 表示 ,0表示正数,1表示负数;
第1位到第11位:储存指数部分, e 表示 ;
第12位到第63位:储存小数部分(即有效数字),f 表示。
十进制的小数如0.1和0.2等都会被转换成二进制,但由于浮点数用二进制表达时是无穷的,所以相加时会出错。
0.1 -> 0.0001100110011001101...(无限)
0.2 -> 0.00110011001100110011...(无限)
0.5 -> 0.1(有限)
2.8 -> 10.11001100110011001101...(无限)
异常得到缓解:
经过放大小数后在放大倍数倍率内的小数正常,但是在倍率外的还是会出现无限循环异常
let result
result = 3*(2.8* 1000000000)/1000000000;
console.log('result:',result);
解决异常的推理过程:
运算出错可能是类型层级的错误,试着转化类型。使用toFixed()处理,但只是使用toFixed()反而还引入了相加时当做字符串相加的新问题
let result
result = (3*(2.8* 1000000000).toFixed()+(2345* 1000000000).toFixed())/1000000000;
console.log('result:',result);
问题解决:
使用toFixed()处理后再加上Number()进行数字类型转化,无限循环小数问题虽然解决了,但是这种转化操作是去小数的,所以精度还是取决于相乘倍数
let result
result = (3*Number((2.8* 1000000000).toFixed())+Number((2345* 1000000000).toFixed()))/1000000000;
console.log('result:',result);
特殊情况:
除此之外还发现如果是在数组中的小数运算是没有这个异常的,估计是数组的运算中包含自动的类型转化,可以去除此问题,所以运算异常在数组运算时不体现
let numberArray = [2.8,1.0000001,3.00000000000002]
let count = 0;
for (let k = 0; k < numberArray.length; k++) {
count += numberArray[k];
}
const result = count;
console.log('result:',result);