答:
- 计算机在计算和有存储数据时,都是使用二进制
- 十进制的0.1和0.2转成二进制时是无限循环的,计算机资源有限无法精确的取值
- JS使用IEEE 754二进制浮点数规范
- 二进制小数存储限制为52位,多余的位数会被舍入
原因·:
计算机使用的是二进制,涉及到计数都会将数字转化成二进制来计算,然后将计算结果生成十进制返回,两个不精确的数相加导致偏差
十进制转化成小数规则:小数×2 乘积取整数位 一直到积数小数位为0 若遇到无限循环,取到你认为足够精度的小数为止
例如:
0.1(十进制)转为二进制 :
式子 | 乘积整数位 |
---|---|
0.1*2=0.2 | 0 |
0.2*2=0.4 | 0 |
0.4*2=0.8 | 0 |
0.8*2=1.6 | 1 |
0.6*2=1.2 | 1 |
0.2*2=0.4 | 0 |
0.4*2=0.8 | 0 |
0.8*2=1.6 | 1 |
0.6*2=1.2 | 1 |
....... | ....... |
0.2(十进制)转为二进制
式子 | 乘积整数位 |
---|---|
0.2*2=0.4 | 0 |
0.4*2=0.8 | 0 |
0.8*2=1.6 | 1 |
0.6*2=1.2 | 1 |
0.2*2=0.4 | 0 |
0.4*2=0.8 | 0 |
0.8*2=1.6 | 1 |
0.6*2=1.2 | 1 |
0.2*2=0.4 | 0 |
........ | ....... |
蓝色部分和粉色部分一样接下来无限循环
所以: 0.1转化成二进制为(乘积整数位) 0.0 0011 0011 0011.....
0.2转化成二进制为 (乘积整数位) 0.0011 0011 0011.....
因此: 相加会有精度损失 不可能是0.3
---------------------------------------------------------------------------------------------------------------------------------
扩展:
-
使用 toString() 方法把十进制转为其他进制:
var x = 28;// 10进制 console.log(x.toString(2)); //把十进制转为2进制 console.log(x.toString(8));//把十进制转为8进制 console.log(x.toString(16));//把十进制转为16进制
-
使用 parseInt() 方法把其他进制转为十进制:
-
parseInt() 方法,第一个参数为要转换的字符串,第二个参数指定字符串的进制
var x = "110";//二进制的字符串 console.log(parseInt(x, 2));//把这个字符串当做二进制,转为十进制 var x = "070";//八进制的字符串 console.log(parseInt(x, 8));//把这个字符串当做八进制,转为十进制 var x = "0x1c";//十六进制的字符串 console.log(parseInt(x, 16));//把这个字符串当做十六进制,转为十进制
-
其他进制的相互转换,先使用parseInt转为十进制,再利用toString变为其他进制