首页 > 浮点数中尾数在二进制情况下丢失精度的疑问

浮点数中尾数在二进制情况下丢失精度的疑问

浮点数中的尾数根据IEEE 754标准转成二进制会产生误差,
例如: 0.9二进制表示为: 1100100100100......(循环了)
那为什么不采用和整数一样的计算方法?


实数是无限的,任意两个实数之间都存在无穷实数,所以采用有限种情况(2^32,2^64或2^80)无论如何都不能表示完所有的整数,所以无论如何都会有些数会损失精度。
如果是你所想的,把某些有限位的小数(整数)可以精确的表示,就要把所有的有限小数表示成(m×10^n),m、n都是整数。那么这样带来的好处仅仅就是0.1+0.2==0.3这样十进制的有限小数可以精确的表示,那么对于1/6+1/3==1/2那么就不再成立了,可是我们写代码并不能保证我们得出的的是有限小数,所以应该说并没有带来什么好处,只是让初学编程的人可以得到0.1+0.2==0.3而已。
那么带来的坏处呢:对于加法,m1×10^n1 + m2×10^n2,那么运算的时候就是先化为指数一样的样子(设n1=n2+1),m1×10^n1+(m2/10)×10^(n2+1)。这一个除以10,浪费CPU时间如果保存成m×2^n的话。那么第一步就是除以2,CPU用位移运算就可以了。他们都会丢失最后的一位有效数字,损失的精度是相似的。
所以这样表示成10进制的形式没带来什么好处,反而有很大的缺点。
在某些语言里,有一种数据类型,叫做货币型,显然是为了保存银行存款金额的,这种东西怎么说也要要求表示的误差不能超过0.01吧。这种数据类型永远会保持小数点后四位的值(10进制),其实这种数据类型保存的就是原始值乘以10000之后的整数。
这算是两种保存不同值的方式,那么第一种指数表示是为了让数据的误差不超过一个相对的值(误差除以数值不超过一个固定的值),也就是我们说的保留多少个有效数字。后面那种就是让误差不超过一个绝对的值,比如是“0.0001/2=0.00005”。那么对于大部分应用我们还是希望使用第一种的。


看来还是有很多人不清楚整数小数。以及定点数和浮点数**。

看来有必要继续安利我的文章:


那为什么不采用和整数一样的计算方法?

用某乎网的一句名言就是:“先问是不是,再问为什么”。

在计算机中,我们表示数通常用 2 中方式:定点和浮点。顾名思义,当我们把小数点固定了,就是定点数。当我们把小数点浮动,就是浮点数。定点数和浮点数都可以用来表示整数和小数。但是我们通常可以用定点数表示小数,但是很少用浮点数表示整数。

在我们表示货币的时候,不能容忍任何的精度损失,虽然货币是小数,比如 3.29, 6.10,我们可以看到,货币的最小单位是分。也就是小数点后面有两位数,这时,我们就可以用定点数表示小数,方法就是把小数点固定在后起第2位的左侧。这样就能精确的表示从 0.00 到 0.99 的任何小数。

更多关于浮点数的介绍,看我的文章吧。


因为所有的正整数都可以精确的表示成2的正整数幂之和,但是有些纯小数不能精确的表示成2的负整数幂之和,因此会产生误差。

其实IEEE754用来表示尾数的方法和表示整数的方法是一样的啊,只不过前者用的是2的负整数幂,后者用的是2的正整数幂,取值范围不一样嘛。


楼主,你质疑浮点表示法没办法精确表示0.9,那么你先想想用你所谓的“整数表示法”是否能精确地表示这个数,然后我们再来谈。


呵呵,知道你会这么说。

那你有没有考虑过表示成1001以后怎么办?怎么运算?10019没错,但它是十进制的,没办法直接用在二进制的运算中。比如1+0.9,按你的逻辑,要先把1扩大10倍变成十进制的10,然后加上9,得19(二进制的10011

这是十进制模拟的二进制,不是二进制!

首先效率就无法接受(计算机里有用十进制表示二进制的先例,BCD码就是,但只适用于整数,并且仅在必要的时候才使用,如果你愿意,可以用任何语言模拟这种表示法)

其次,也是最重要的一点。十进制并不能解决这个问题,遇到1/3这样的怎么办?比如我让你求1.0/3.0的结果,来,你给我表示表示?

【热门文章】
【热门文章】