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

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


当前回答

我很惊讶居然没有人说过:使用连分式。任何有理数都可以用二进制有限地表示。

一些例子:

1/3 (0.3333...)

0; 3

5/9 (0.5555...)

0; 1, 1, 4

10/43 (0.232558139534883720930...).

0; 4, 3, 3

9093/18478 (0.49209871198181621387596060179673...).

0; 2, 31, 7, 8, 5

从这里开始,有多种已知的方法可以在内存中存储整数序列。

除了精确地存储数字外,连分式还有其他一些好处,比如最佳有理逼近。如果您决定提前终止连分式中的数字序列,则剩余的数字(当重新组合为分数时)将给出可能的最佳分数。这是如何找到圆周率的近似值的:

π的连分式:

3; 7, 15, 1, 292 ...

在1处终止序列,得到的分数是:

355/113

这是一个很好的有理近似。

其他回答

你不能用二进制精确地表示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,这不是巧合……

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

让我们暂时撇开以10为底和以2为底的细节。我们问一下,在以b为底的情况下,哪些数字有终止表示,哪些数字没有?稍微思考一下,我们就知道一个数字x有一个终止的b表示,当且仅当存在一个整数n,使得x b^n是一个整数。

例如,x = 11/500有一个终止10表示,因为我们可以选择n = 3,然后x b^n = 22,一个整数。但是x = 1/3不是,因为不管n取多少都不能消掉3。

第二个例子促使我们思考因子,我们可以看到,对于任何有理数x = p/q(假设是最小值),我们可以通过比较b和q的质因数分解来回答这个问题。如果q有任何不在b的质因数分解中的质因数,我们将永远无法找到一个合适的n来摆脱这些因数。

因此,对于以10为底的任何p/q,其中q有除2或5之外的素数因子,将没有终止表示。

现在回到以10和2为底,我们看到任何以10为底的有理数都是p/q的形式当q的质因数分解中只有2s和5s时;当q的质因数分解中只有2时,同样的数会有一个终止的2表示。

但其中一个案例是另一个案例的子集!每当

Q的质因数分解只有2

这显然也是正确的

Q的质因数分解只有2和5

换句话说,只要p/q有终止的2表示,p/q就有终止的10表示。然而反过来就不成立了——只要q的质因数分解中有一个5,它就会有一个终止的10表示,而不是终止的2表示。这是其他答案提到的0.1的例子。

这就是问题的答案了因为2的质因数是10的质因数的子集,所以所有以2结尾的数都是以10结尾的数,反之则不然。不是61比6.1,而是10比2。

最后提醒一下,如果有些人使用17进制,而我们的计算机使用5进制,你的直觉永远不会被这引入歧途——在这两种情况下都不会有(非零,非整数)数字终止!

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

根(数学)原因是,当你处理整数时,它们是可数无限的。

这意味着,即使它们的数量是无限的,我们也可以“数出”序列中的所有项目,而不会跳过任何一项。这意味着,如果我们想要在列表中的第610000000000000th位置上得到一项,我们可以通过一个公式来计算它。

然而,实数是无限的。你不能说“给我位置610000000000000的真实数字”并得到一个答案。原因是,即使在0到1之间,当考虑浮点值时,也有无限个值。这同样适用于任何两个浮点数。

更多信息:

http://en.wikipedia.org/wiki/Countable_set

http://en.wikipedia.org/wiki/Uncountable_set

更新: 很抱歉,我似乎误解了这个问题。我的回答是关于为什么我们不能表示每一个真实的值,我没有意识到浮点数被自动归类为理性。

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