为何np.spacing的最小绝对值小于float64类型的eps?
首先将你提到的文档内容翻译成中文:
它可以被视为EPS的泛化:
spacing(np.float64(1)) == np.finfo(np.float64).eps,并且对于任何有限的x,x和x + spacing(x)之间不存在任何可表示的数。
你观察到np.spacing(a)的最小值小于np.float64类型的eps,核心原因在于:eps是1.0这个特定数值对应的浮点数间距,而np.spacing(x)返回的是x所在位置的浮点数间距,这个间距会随x的大小变化——x越小,间距越小。
具体原理
双精度浮点数(float64)遵循IEEE 754标准,其可表示的数值是离散且不均匀分布的:
- 在接近0的数值区域,浮点数的密度极高,两个相邻可表示数的绝对间距非常小;
- 随着数值增大,间距会呈指数级扩大。
np.finfo(np.float64).eps的定义是1.0到下一个更大的可表示浮点数的距离,值为2^-52 ≈ 2.220446049250313e-16。而np.spacing(x)返回的是x到下一个更大可表示数的距离,这个值与x的量级成正比:x越小,对应的间距就越小;x越大,间距也会随之变大。
结合你的示例分析
你用np.random.uniform(size=10)生成的是0到1之间的随机数,其中必然包含一些接近0的小数值(比如量级在1e-20左右的数)。对于这些小数值,它们对应的浮点数间距(即np.spacing(x))自然会远小于1.0对应的eps,因此取这些spacing值的最小绝对值后,结果会比eps小。
比如你得到的1.3552527156068805e-20,对应的x应该是一个量级在1.355e-20 * 2^52 ≈ 6.1e-5左右的数,这个数远小于1.0,所以它的spacing远小于eps。
内容的提问来源于stack exchange,提问作者KG in Chicago

