为什么所有的浮点数都可以用十进制表示?

How come all floating-point numbers can be represented in decimal?

众所周知,并不是所有的十进制数都能用二进制浮点数精确表示。

不过,似乎所有的二进制浮点数都可以用十进制表示。

为什么没有不能用十进制表示的浮点数,反之则不然?好像有点不对称。

二进制floating-point格式表示数字为±M•2e,其中 M 是指定范围内的整数,e 是指定范围内的整数指数。 (也可以定义表示,其中 M 是 fixed-point 数字而不是整数。这些在数学上等同于对边界进行适当调整。)

一个十进制数相当于±M•10e(一般对于一些当然还有 Me。例如,3.4 相当于 +34•10−1.

对于形式为±M•10e的任何十进制数字,我们可以重写:±M•10e = ±M•(5•2)e = ±M•(5e•2e) = ±(M•5e)•2e .现在,如果 M•5e 是范围内的整数,则这是二进制 floating-point 代表。但是,如果 M•5e 不是整数,如 34•5−1,没有办法让它成为整数。此数字无法以二进制 floating-point 格式表示。

相反,考虑一个二进制floating-point数±M•2e.如果e是非负数,则为整数,所以这已经是十进制数字形式;它是 100 的整数倍。如果e为负数,我们可以改写为:±M•2e = ±M•2e•5e•5e = ±M•10e•5e = ± (M•5e)•10e 。那么,由于e为负,M•5e是一个整数,所以±(M•5e)•10e是整数乘以十的幂的十进制形式

换句话说,我们可以将任何还不是整数的二进制 floating-point 数乘以 10 直到得到整数,从而将其变成整数。这是因为 2 是 10 的因数,所以每次乘以 10 都会抵消 floating-point 表示中 2 的一个负幂。

相反,给定一个非整数的十进制数字,例如 .1,我们不能总是将其变成整数,因为乘以 2 不会抵消其中的 5 的负幂。

换个角度看


二进制浮点数具有如下值的各个二进制数字:

...
24 = 16.0
23 = 8.0
22 = 4.0
21 = 2.0
20 = 1.0
2-1 = 0.5
2-2 = 0.25
2-3 = 0.125
2-4 = 0.0625
...

然后很容易看出 large + 2 的幂和 2 的 large - 幂是精确表示的十进制值。

由于所有的二进制浮点数都是其位数的和,所以所有二进制浮点数的十进制值就是上述可表示的十进制值的简单和。


基数为 10 的数字(我们写成“123.456”)并不总是可以用浮点二进制表示,因为像 0.1、0.01、0.001、m 等单个数字缺乏精确的 有限 二进制 FP 表示。

10-1 = 0.00011001100110011...2