numpy不同浮点类型精度限制:计算1/i相邻项不可区分的对应i值
计算逻辑说明
相邻两项1/i与1/(i+1)的差值为:
1/i - 1/(i+1) = 1/(i*(i+1))
当这个差值小于等于阈值E(或浮点类型本身的最小可分辨误差)时,两个值就无法被区分。
1. 给定任意阈值E时的i值计算
解不等式 1/(i*(i+1)) < E,因为i较大时i*(i+1)≈i²,可近似得到:i ≈ √(1/E)
和你给出的示例完全匹配:E=0.01时,√(1/0.01)=10,对应无法区分1/10和1/11。
2. 最小E及对应i值计算
这里的最小E就是浮点类型本身的精度上限,也就是对应数值点的最小可分辨绝对差,计算逻辑如下:
- 每种浮点类型都有固定的相对精度(机器epsilon),即
np.finfo(np.floatXX).eps,代表该类型可以表示的两个同量级数值的最小相对差:- float16相对epsilon≈0.0009766
- float32相对epsilon≈1.192e-7
- float64相对epsilon≈2.22e-16
- 数值
x=1/i对应的最小可分辨绝对差为x * eps = (1/i) * eps - 当相邻两项的差值小于等于这个绝对差时,两者无法区分,即:
1/(i*(i+1)) ≤ (1/i)*eps
约掉公因子后近似可得i ≈ 1/eps - 对应最小E的近似值为
eps²,比如float16的最小E≈9.5e-7。
不同浮点类型的理论与实际测试i值对比:
| 浮点类型 | 理论近似i值 | 实际测试i值 |
|---|---|---|
| float16 | ~1024 | 1464 |
| float32 | ~838万 | 11864338 |
| float64 | ~4.5e15 | 同量级 |
实际值和理论近似值的差异来自浮点数表示的离散性,实际运行断点测试得到的结果更准确
通用函数f(i)的最大可区分i计算方法
对于任意单调函数f(i),只要满足以下不等式,相邻的f(i)与f(i+1)就无法被对应浮点类型区分:
abs(f(i) - f(i+1)) < np.finfo(浮点类型).eps * abs(f(i))
解该不等式即可得到最大可区分的i值。
验证代码
你给出的断点测试逻辑完全正确,可直接运行得到准确结果:
import numpy as np # float16测试 for i in range(1000, 2000): if not np.float16(1/i) > np.float16(1/(i+1)): print(f"float16断点i:{i}") break # float32测试 for i in range(int(1e7), int(1.3e7)): if not np.float32(1/i) > np.float32(1/(i+1)): print(f"float32断点i:{i}") break
内容的提问来源于stack exchange,提问作者sten
相关产品推荐
相关产品推荐

