有几个关于浮点表示法的问题被提交给了SO。例如,十进制数0.1没有精确的二进制表示,因此使用==操作符将其与另一个浮点数进行比较是危险的。我理解浮点表示法背后的原理。

我不明白的是,为什么从数学的角度来看,小数点右边的数字比左边的数字更“特殊”?

例如,数字61.0具有精确的二进制表示,因为任何数字的整数部分总是精确的。但6.10这个数字并不准确。我所做的只是把小数点移了一位突然间我就从精确乌托邦变成了不精确镇。从数学上讲,这两个数字之间不应该有本质差别——它们只是数字。

相比之下,如果我把小数点向另一个方向移动一位,得到数字610,我仍然在Exactopia。我可以继续往这个方向(6100,610000000,610000000000000)它们仍然是完全,完全,完全的。但是一旦小数点越过某个阈值,这些数字就不再精确了。

这是怎么呢

编辑:为了澄清,我不想讨论诸如IEEE之类的行业标准表示,而是坚持我所相信的数学上的“纯粹”方式。以10为基数,位置值为:

... 1000  100   10    1   1/10  1/100 ...

在二进制中,它们将是:

... 8    4    2    1    1/2  1/4  1/8 ...

这些数字也没有任意的限制。位置向左和向右无限增加。


当前回答

有理数的数量是无限的,而用来表示有理数的比特的数量是有限的。见http://en.wikipedia.org/wiki/Floating_point # Accuracy_problems。

其他回答

这是个好问题。

你所有的问题都是基于“我们如何表示一个数字?”

所有的数字都可以用十进制表示,也可以用二进制(2的补码)表示。所有人!!

但有些(大多数)需要无穷多个元素(二进制位置为“0”或“1”,十进制表示为“0”,“1”到“9”)。

比如十进制表示的1/3(1/3 = 0.3333333…<-包含无限个“3”)

比如二进制中的0.1 (0.1 = 0.00011001100110011....<-带有无限个“0011”)

一切都在这个概念中。由于您的计算机只能考虑有限的数字集(十进制或二进制),只有一些数字可以准确地表示在您的计算机…

乔恩说过,3是质数,不是10的因数,所以1/3不能用以10为底的有限个数来表示。

即使使用任意精度的算术,以2为基数的编号位置系统也不能完全描述6.1,尽管它可以表示61。

对于6.1,我们必须使用另一种表示法(比如十进制表示法,或者允许以2为底或以10为底表示浮点值的IEEE 854)。

问题是你并不知道这个数字是否真的是61.0。考虑一下:

浮动a = 60; 浮动b = 0.1; c = a + b * 10;

c的值是多少?它不是61,因为b不是。1因为。1不是精确的二进制表示。

数字61.0确实有一个精确的浮点运算——但这并不是对所有整数都适用。如果您编写了一个循环,将一个双精度浮点数和一个64位整数都加了1,最终您将达到这样的情况:64位整数完美地表示一个数字,而浮点数却不能——因为没有足够的有效位。

只是在小数点右边求近似值要容易得多。如果你把所有的数字都写成二进制浮点数,这就更有意义了。

另一种思考的方式是,当你注意到61.0完全可以用10为底表示时,移动小数点并不会改变这一点,你是在执行10的幂乘法(10^1,10^-1)。在浮点数中,乘以2的幂并不影响数字的精度。试着用61.0反复除以3来说明一个非常精确的数字是如何失去它的精确表示的。

这和你不能精确地以10为基数表示1/3的原因是一样的,你需要说0.33333(3)。在二进制中,这是相同类型的问题,只是发生在不同的数字集上。

有理数的数量是无限的,而用来表示有理数的比特的数量是有限的。见http://en.wikipedia.org/wiki/Floating_point # Accuracy_problems。