在很多编程语言中,发现会出现0.1*3==0.3最后结果为false的情况,查了下资料记录为下:
1.浮点数的二进制表示
在编程语言中,类如java,js ,c ,数据都是以二进制的形式存在磁盘中的,数字也不列外,当计算机拿到一个数字存储时 ,会将数字转换成二进制存在磁盘中,所以我们首先弄清楚数字怎样转换为二进制:
- 整数部分乘2取余后逆向排序
- 小数部分乘以2取整数部分,知道小数部分为0为止,然后顺序排序
所以,0.1在计算机转换为二进制时不断进行乘2操作
- 0.1×2 = 0.2 取0;
- 0.2×2 = 0.4 取0;
- 0.8×2 = 0.8 取0;
- 0.6×2 = 1.6 取1;
- 0.2×2 = 1.2 取1;
- 0.1×2 = 0.2 取0;
.....
所以0.2在计算机中存储二进制位=>0.0001100110011...(循环0011)
而0.2在计算机转换为二进制时不断进行乘2操作
- 0.2×2 = 0.4 取0;
- 0.8×2 = 0.8 取0;
- 0.6×2 = 1.6 取1;
- 0.2×2 = 1.2 取1;
- 0.1×2 = 0.2 取0;
.....
所以0.2在计算机中存储二进制位=>0.001100110011...(循环0011)
2.IEEE 754 规范
java语言采用的IEEE754的规范来存储浮点数,即float和double两种类型
float类型即具有24位有效数位,加上符号位1位+尾数23位 = 24位
因为float具有24位有效数位 ,除去1位符号位 即有23位存储位对应7~8位有效十进制数字
double类型即具有53位有效数位,加上符号位1位+尾数52位 = 53位
因为double具有24位有效数位 ,除去1位符号位 即有52位存储位对应15~16位有效十进制数字
0.1在计算机中有效存储为52位,即=> 0.00011001100110011001100110011001100110011001100110011001
0.2在计算机中有效存储为52位,即
=> 0.00110011001100110011001100110011001100110011001100110011
那么两者相加0.1的二进制+0.2的二进制
0.00011001100110011001100110011001100110011001100110011001
加
0.00110011001100110011001100110011001100110011001100110011
=
0.01001100110011001100110011001100110011001100110011001100
转换为10进制为0.30000000000000004!=0.3
所以在java ,js python c等编程语言中0.1+0.2!=0.3都是精度丢失的问题