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

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


当前回答

你们知道整数,对吧?每一位代表2^n

2 ^ 4 = 16 2 ^ 3 = 8 2 ^ 2 = 4 2 ^ 1 = 2 2 ^ 0 = 1

浮点数也是一样的(有一些区别),但是比特代表2^-n 2 ^ 1 = 1/2 = 0.5 2 ^ 2 = 1 / (2 * 2) = 0.25 2 ^ 3 = 0.125 2 ^ 4 = 0.0625

浮点二进制表示法:

符号指数分数(我认为无形的1被附加到分数) B11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0

其他回答

如果你有足够的空间,十进制数可以精确地表示出来——只是不能用浮点二进制数表示。如果您使用浮点小数点类型(例如System。. net中的十进制),那么许多不能用二进制浮点数精确表示的值都可以被精确表示。

让我们从另一个角度来看——以10为基数,你可能会觉得舒服,你不能准确地表示1/3。这是0.3333333……(重复)。不能将0.1表示为二进制浮点数的原因与此完全相同。你可以表示3 9和27,但不是1/3 1/9或1/27。

问题是3是质数,不是10的因数。当你想将一个数乘以3时,这不是一个问题:你总是可以乘以一个整数而不会遇到问题。但是当你除以一个质数而不是底数的因数时,你就会遇到麻烦(如果你试图用1除以这个数,你就会遇到麻烦)。

虽然0.1通常被用作精确十进制数的最简单例子,它不能用二进制浮点数精确表示,但可以说0.2是一个更简单的例子,因为它是1/5,而5是导致十进制和二进制之间存在问题的素数。


边注:处理有限表示的问题:

Some floating decimal point types have a fixed size like System.Decimal others like java.math.BigDecimal are "arbitrarily large" - but they'll hit a limit at some point, whether it's system memory or the theoretical maximum size of an array. This is an entirely separate point to the main one of this answer, however. Even if you had a genuinely arbitrarily large number of bits to play with, you still couldn't represent decimal 0.1 exactly in a floating binary point representation. Compare that with the other way round: given an arbitrary number of decimal digits, you can exactly represent any number which is exactly representable as a floating binary point.

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

你不能用二进制精确地表示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并不总是会产生更高的精度,因为在某些情况下,浮点数将不得不使用指数来表示数字的大小,这样也会失去一些精度。

你们知道整数,对吧?每一位代表2^n

2 ^ 4 = 16 2 ^ 3 = 8 2 ^ 2 = 4 2 ^ 1 = 2 2 ^ 0 = 1

浮点数也是一样的(有一些区别),但是比特代表2^-n 2 ^ 1 = 1/2 = 0.5 2 ^ 2 = 1 / (2 * 2) = 0.25 2 ^ 3 = 0.125 2 ^ 4 = 0.0625

浮点二进制表示法:

符号指数分数(我认为无形的1被附加到分数) B11 b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0