关于Java float型精度缺失的一点疑问

来源:百度知道 编辑:UC知道 时间:2024/06/15 02:02:59
看过一些关于浮点型小数运算时精度丢失的原理介绍和float型内存原理的文章。但还是有一点不太明白:
为什么 2.0f - 1.9f = 0.100000024
而 2.0f - 0.9f = 1.1

1.9f在内存中的二进制记载:00111111111100110011001100110011
0.9f在内存中的二进制记载:00111111011001100110011001100110

按说它们的小数部分都是个循环小数(二进制),都存在截掉尾巴的问题,可是为什么 2.0f - 0.9f 的结果确正好 = 1.1呢??
望高人指点
谢谢youerkang的回答,我按照你的试验成功了。但是,还是有疑问:
System.out.println( 2.0f - 1.9f );
System.out.println(2.0f - 0.9f );
System.out.print("\n");
System.out.printf("%1.20f", 2.0f - 1.9f );
System.out.print("\n");
System.out.printf("%1.20f", 2.0f - 0.9f );
System.out.println("\n");
System.out.println(0.10000002384185791000f);
System.out.println(1.10000002384185800000f);

的结果是:
0.100000024
1.1

0.10000002384185791000
1.10000002384185800000

0.100000024
1.1

为什么println对是否存在整数位的小数打印的时候,有所不同呢?
现在这个问题似乎转移到了对print的实现的研究了...
<

2.0f - 0.9f = 1.1也是一个不精确的表示,其实在机器里面是1.10000...只是0比较多,已经超出你的打印函数(println之类的)的默认精度而已。如果使用printf函数强行指定打印精度的话,比如System.out.printf("%1.10f", 2.0f - 0.9f );会看到打印的结果是1.1000000238,也不是精确的1.1。不知道这样解释清不清楚了?

补充:
关于float的精度:
其实是由于toJavaFormatString()的缘故,你可以打开java的print函数源代码看一看,会发现最终是一直追溯到toJavaFormatString()这个函数,它会在将float变量转换为String类型时做一个精度的截断。而使用printf时,是不用这个toJavaFormatString()函数来完成转换的。