有几个关于浮点表示法的问题被提交给了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 ...

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


当前回答

一个简单的答案是:计算机没有无限的内存来存储分数(在以科学记数法的形式表示十进制数之后)。根据IEEE 754双精度浮点数标准,我们只有53位的限制来存储分数。 欲了解更多信息:http://mathcenter.oxford.emory.edu/site/cs170/ieee754/

其他回答

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

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

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

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

你不能用二进制精确地表示0.1,就像你不能用传统的英国尺测量0.1英寸一样。

英国的尺子,就像二进制分数一样,都是关于一半的。你可以测量半英寸,或四分之一英寸(当然是一半),或八分之一,或十六分之一,等等。

If you want to measure a tenth of an inch, though, you're out of luck. It's less than an eighth of an inch, but more than a sixteenth. If you try to get more exact, you find that it's a little more than 3/32, but a little less than 7/64. I've never seen an actual ruler that had gradations finer than 64ths, but if you do the math, you'll find that 1/10 is less than 13/128, and it's more than 25/256, and it's more than 51/512. You can keep going finer and finer, to 1024ths and 2048ths and 4096ths and 8192nds, but you will never find an exact marking, even on an infinitely-fine base-2 ruler, that exactly corresponds to 1/10, or 0.1.

不过,你会发现一些有趣的事情。让我们看看我列出的所有近似值,对于每一个近似值,明确地记录0.1是大是小:

fraction decimal 0.1 is... as 0/1
1/2 0.5 less 0
1/4 0.25 less 0
1/8 0.125 less 0
1/16 0.0625 greater 1
3/32 0.09375 greater 1
7/64 0.109375 less 0
13/128 0.1015625 less 0
25/256 0.09765625 greater 1
51/512 0.099609375 greater 1
103/1024 0.1005859375 less 0
205/2048 0.10009765625 less 0
409/4096 0.099853515625 greater 1
819/8192 0.0999755859375 greater 1

现在,如果向下读最后一列,就会得到0001100110011。1/10的无限重复二进制分数是0.0001100110011,这不是巧合……

如果你用浮点数做一个足够大的数(它可以做指数),那么小数点前也会不精确。所以我不认为你的问题是完全正确的,因为前提是错误的;移位10并不总是会产生更高的精度,因为在某些情况下,浮点数将不得不使用指数来表示数字的大小,这样也会失去一些精度。

分数和整数可以构成比例尺。有些分数,如1/7,如果没有很多很多的小数,就不能用十进制形式表示。因为浮点数是基于二进制的,所以特殊情况会发生变化,但同样的精度问题也会出现。