/*问题查看*/
//感觉是true,结果却是false
var num1 = 0.1;
var num2 = 0.2;
var result = num1+num2;
console.log(result);
//16位数与17位数的判断结果是true
var num3 = 9999999999999999;
var num4 = 10000000000000001;
console.log(num3 == num4);
/*问题原因*/
计算机中数据的存储是采用二进制来存储的,这就意味着和现实中的数据对比来看,很多无理数是没有办法用二进制精确描述的。
例如:1.33333... 3.1415926...
当必须进行二进制存储的时候,计算机内部会对存储数据进行“简化处理”,而这个简化操作,就是精度丢失的由来
/*问题解释*/
直接对0.1进行64位二进制转换即可
0.1*2=0.2 //0
0.2*2=0.4 //00
0.4*2=0.8 //000
0.8*2=1.6 //0001
0.6*2=1.2 //00011
0.2*2=0.4 //000110
0.4*2=0.8 //0001100
0.8*2=1.6 //00011001
0.6*2=1.2 //000110011
0.2*2=0.4 //0001100110
0.4*2=0.8 //00011001100
0.8*2=1.6 //000110011001
0.6*2=1.2 //0001100110011
0.2*2=0.4 //00011001100110
0.4*2=0.8 //000110011001100
0.8*2=1.6 //0001100110011001
0.6*2=1.2 //00011001100110011
...
发现最终无法得到完整的结果1.0,
只能无限乘下去
这样0.1的二进制最终就会成为
0.0001 1001 1001 1001...无限循环
但是长度最高只有64位,所以
最终0.1的二进制就只能近似约等于
0.0001100110011001100110011001100110011001100110011001100110011001
问题出现,这个数字只是近似等于0.1而不是真正的0.1
因为0.1的二进制是一个无限循环数,64位存储的计算机根本无法保存
所以,舍掉的一部分就成为了那个误差。
而所谓的精度极限,指的就是64位只能保证数据精确到64位,
再向后由于计算机位数限制,精度无法到达,故称为精度极限。
/*问题验证*/
0.0001100110011001100110011001100110011001100110011001100110011001
这个二进制反向计算,转换成10进制
0*2^-1 + 0*2^-2 + 0*2^-3 + 1*2^-4 + 1*2^-5 + 0*2^-6 + 0*2^-7 + 1*2^-8 +
1*2^-9 + 0*2^-10 + 0*2^-11 + 1*2^-12 + 1*2^-13 + 0*2^-14 + 0*2^-15 + 1*2^-16 +
1*2^-17 + 0*2^-18 + 0*2^-19 + 1*2^-20 + 1*2^-21 + 0*2^-22 + 0*2^-23 + 1*2^-24 +
1*2^-25 + 0*2^-26 + 0*2^-27 + 1*2^-28 + 1*2^-29 + 0*2^-30 + 0*2^-31 + 1*2^-32 +
1*2^-33 + 0*2^-34 + 0*2^-35 + 1*2^-36 + 1*2^-37 + 0*2^-38 + 0*2^-39 + 1*2^-40 +
1*2^-41 + 0*2^-42 + 0*2^-43 + 1*2^-44 + 1*2^-45 + 0*2^-46 + 0*2^-47 + 1*2^-48 +
1*2^-49 + 0*2^-50 + 0*2^-51 + 1*2^-52 + 1*2^-53 + 0*2^-54 + 0*2^-55 + 1*2^-56 +
1*2^-57 + 0*2^-58 + 0*2^-59 + 1*2^-60 + 1*2^-61 + 0*2^-62 + 0*2^-63 + 1*2^-64
计算加和是:0.09999999999999999167332731531133
由于存储精度的极限,导致二进制存储丢失内容
而丢失的内容反过来又导致10进制转换时不足以满足实际标准
便产生了精度丢失
即所谓的0.3-0.2不等于0.1的问题
|