这很有效!如果所讨论的数字的大小足够小,则 int∘floor = ⌊⋅⌋ 是 IEEE 浮点表示的一个属性,但 int(floor(2.3)) 可能为 1 时可能会有不同的表示。
这篇文章解释了为什么它在这个范围内工作。
在双精度中,您可以毫无问题地表示 32 位整数。 不可能有任何舍入问题。更准确地说,双精度可以表示 253 和 -2 之间的所有整数53.
简短说明:一个 double 最多可以存储 53 个二进制数字。当您需要更多时,数字会在右侧用零填充。
因此 53 是可以存储的最大数字而无需填充。自然,所有需要较少位数的(整数)数字都可以准确存储。
向111(省略)111(53 个一)加一得到 100...000,(53 个零)。我们知道,我们可以存储 53 位数字,这使得最右边的零填充。
这就是 253 的来源。
更多细节:我们需要考虑 IEEE-754 浮点的工作原理。
1 bit 11 / 8 52 / 23 # bits double/single precision
[ sign | exponent | mantissa ]
然后按如下方式计算数量(不包括此处不相关的特殊情况):
-1符号 × 1.mantissa ×2指数 - 偏差
其中 bias = 2exponent - 1 - 1,即双精度/单精度分别为 1023 和 127。
知道乘以 2X 只是将所有位 X 位向左移动,很容易看出任何整数必须具有所有尾数中从小数点右边到零的位。
除零以外的任何整数都具有以下二进制形式:
1x...x 其中 x-es 表示 MSB 右侧的位(最高有效位)。
因为我们排除了零,所以总是有一个 MSB 为一,这就是它不被存储的原因。为了存储整数,我们必须把它变成上述形式:-1sign × 1.mantissa ×2exponent - bias。 p>
这与将位移动到小数点后的含义相同,直到 MSB 左侧只有 MSB。然后将小数点右边的所有位存储在尾数中。
由此可知,除了MSB之外,我们最多可以存储52个二进制数字。
由此可见,显式存储所有位的最大数是
111(omitted)111. that's 53 ones (52 + implicit 1) in the case of doubles.
为此,我们需要设置指数,使小数点移动 52 位。如果我们将指数加一,我们无法知道小数点后右边的数字。
111(omitted)111x.
按照惯例,它是 0。将整个尾数设置为零,我们会收到以下数字:
100(omitted)00x. = 100(omitted)000.
这是一个 1 后跟 53 个零,52 个存储和 1 由于指数而添加。
它代表253,它标志着我们可以准确表示所有整数的边界(负数和正数)。如果我们想给 253 加一,我们必须将隐含的零(用 x 表示)设置为一,但这是不可能的。