其他分享
首页 > 其他分享> > 深入了解浮点精度(三。浮点不准确)

深入了解浮点精度(三。浮点不准确)

作者:互联网

上一章:深入了解浮点精度(二。浮点在计算机的存储)

通过上章,我们知道,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.1

0 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