深入了解浮点精度(三。浮点不准确)
作者:互联网
通过上章,我们知道,4.25的二进制是100.01,4.75 = 100.11。
但仔细想想,就会觉得不对劲,
浮点是不是只能表示1被2或2的倍数除的小数和呢?
带着这个疑问,我们来拜访下4.1,这次我们和4.125以及4.0625一起来拜访
0 12345678 12345678 12345678 1234567
0 10000001 00001000 00000000 0000000 4.125
0 10000001 00000110 01100110 0110011 4.1
0 10000001 00000100 00000000 0000000 4.0625
在打印里,我们发现4.1大于4.0625,小于4.125.这也符合我们的常识。
其中4.625和 4.125和4.25一样比较特殊,都可以表示1被2或2的倍数除的小数和呢.所以在二进制里,它的描述很简单,很快就到了尽头。
但是4.1就不一样了,无论怎么搞,会发现都无法找到尽头,如果位数是无限的,它可以搞到无限位,但最终都是越来越接近1,就像高等数学的极限一样,下面类似下面这个公式
1 = 1/2 + 1/4 + 1/8 +......1/n+.......
可是你虽然无限位,但电脑存储可达不到无限位了,怎么办呢?这就牵涉到精度的问题了。
规定只存储一定量的尾巴,多余的尾巴不要。
如float类型,尾数位置是32-8-1 = 23尾。
那么它只能存储23位的尾数,所以这就是它的精度,再往后的无限循环或者有限的尾巴我就不表示了,我就表示这么多。
那么由此我们可以得出,double类型双精度确实比float精度要高的多,因为它的尾数位更长。
可以这样又引出了另一个问题。
我们来尝试打印一下4.0999999f的位
0 12345678 12345678 12345678 1234567
0 10000001 00001000 00000000 0000000 4.125
0 10000001 00000110 01100110 0110011 4.10 10000001 00000110 01100110 0110011 4.0999999f
0 10000001 00000100 00000000 0000000 4.0625
这时候就会发现,我去,这4.1和4.0999999是一模一样的吗?
不,它们不是一样的,只是可怜的是,它们在有限的23尾内是一样的,float类型就只能存储这么多
我们再测试一下这个:
System.out.println(4.1f == 4.0999999f);
结果是true
哈哈哈哈~~~是不是再也不敢再用浮点数据类型了?
well,没有办法,就是这样,你平时所用的浮点数据类型就是这样,它不会考虑精度之外的数,因为本身它也从来没有存储过。
事实上,System.out.println(4.1f == 4.0999999f);这句会报黄线,编译器认为是没有意义的代码。相当于true==true
这个时候,我们再来看看第一章的一个现象:
System.out.println(0.05 + 0.01);
0.060000000000000005
为什么会出现这种现象呢?现在就可以推测解释了。
在计算机里,不是0.05+0.01,很有可能是0.049999999998 + 0.01000000007(数据不准,只是说明思想)
看到浮点数如此坑爹,有的同学可能不淡定了,那该怎么办呢?
我平时该怎么对浮点型的数据进行运算呢?请看下一章。
标签:10000001,4.1,4.0999999,12345678,浮点,精度,准确 来源: https://blog.csdn.net/dmw412724/article/details/97407853