二进制无法精确存储0.1

♂十进制下一个简单的小数0.1,在二进制下却变成无限循环小数0.0 0011 0011 0011…进而无法精确的存储,是不是说明二进制有缺陷?
♂答案是否定的:
(1)小数分为有限小数、无限循环小数、无限不循环小数,其中有限小数和无限循环小数都可以转换成有理数范围内的分数形式,十进制下的0.1也就是分数1/10;
(2)无论用多少进制表示小数,小数的值都是通过∑m*n^k计算得到(n为进制数、m为底数、k为指数),十进制下的1/3(0.3…)、1/7(0.142857…)是无限循环小数,但它们分别和七进制下却都表示为有限小数0.1;
(3)因此分数在所有进制下都存在无限循环小数,只是各进制下哪些分数属于无限循环小数的这个范围是不一样的;

0.1+0.2不等于0.3

♀在JavaScript环境和Java的System.out.println打印0.1+0.2的结果都是 “0.30000000000000004”,在C/C++语言环境下printf打印的结果是”0.300000”,是不是说明C/C++表示小数的精度更高?
♀答案是否定的:
(1)自1985年起,包括C、C++、Java、JavaScript在内的所有编程语言都采用IEEE-754标准实现浮点数的存储;
(2)Java和JavaScript环境下打印值默认保留了小数点后17位,而在C/C++环境下打印值默认保留了6位是产生上述差异现象的原因;
(3)C/C++环境下通过以下语句显式得设置打印小数点后17位同样会打印”0.30000000000000004”;

1
printf("0.1+0.2== %.17f\n", 0.1+0.2);

0.1+0.1等于0.2

▲在各环境下”0.1+0.2==0.3”结果是false,”0.1+0.1==0.2”结果却是true,而且在JavaScript环境和Java的System.out.println打印”0.1+0.1”的结果都是”0.2”,为什么?
▲原因是:
(1)按照IEEE-754存储,0.1和0.1的存储值相加结果存储后的值与0.2直接存储的值一致;
(2)按照IEEE-754存储,0.1和0.2的存储值相加结果存储后的值与0.3直接存储的值不一致;