9.1 浮点精度
浮点数精度是数值计算的基石——忽略它会写出"看似正确实则错误"的代码。量化金融中涉及大量数值运算,理解浮点误差是写出可靠交易系统的前提。
机器 Epsilon
机器 epsilon () 是计算机浮点数系统中,满足 的最小正数。在 IEEE 754 标准中:
| 精度 | 类型 | 机器 epsilon | 有效位数 |
|---|---|---|---|
| 单精度 | float32 | ~7 位 | |
| 双精度 | float64 | ~16 位 |
Python 中可用以下方式验证:
eps = 1.0
while 1.0 + eps != 1.0:
eps /= 2.0
print(f"机器 epsilon = {eps * 2}") # 输出: 2.220446049250313e-16灾难性抵消(Catastrophic Cancellation)
当两个大小相近的数相减时,有效数字大量丢失——这是数值计算中最危险的误差来源之一。
手算实例:
双精度浮点数只有约 16 位有效数字。 在双精度下表示为 。
| 步骤 | 数学运算 | 计算机实际发生了什么 |
|---|---|---|
| 1 | 的第 17 位是 1,但双精度只有 ~16 位,1 被截断 | |
| 2 | 结果 | 计算机认为 |
| 3 | ||
| 4 | 理论正确结果 |
验证:
print((10**16 + 1) - 10**16) # 输出: 0.0如何避免灾难性抵消?
1. 代数变换——共轭有理化
将减法转化为加法或乘法形式。例如,计算 时,分母是两个接近的数相减(灾难性抵消),通过乘以共轭 来消除减法: \frac{1}{\sqrt{x + \delta} - \sqrt{x}} \quad\rightarrow\quad \frac{\sqrt{x + \delta} + \sqrt{x}}{\delta}
### 2. Kahan 求和算法 当需要累加大量浮点数时,使用 Kahan 补偿求和: ```python def kahan_sum(values): """Kahan 补偿求和,减少累积误差""" total = 0.0 compensation = 0.0 # 误差补偿项 for v in values: y = v - compensation t = total + y compensation = (t - total) - y total = t return total ``` ### 3. 使用高精度库 Python 的 `Decimal` 模块或 `math.fsum` 提供了更高精度的数值运算。 --- ## Quant Link:大规模优化中的浮点问题 在**计算期权净值**时,如果两个非常大的头寸方向相反(如一个看涨 + 执行价 100 的空头 + 一个执行价 101 的多头),它们的差值很小但包含关键定价信息——灾难性抵消会**完全抹去**这个价差信号。 ### 常见场景 | 场景 | 风险 | 解决方案 | |------|------|----------| | Greeks 有限差分 | $\epsilon$ 过小导致灾难性抵消 | 选择 $\epsilon \approx \sqrt{\varepsilon_m} \cdot S$ | | 大数相减求价差 | 有效位数丢失 | 代数变换;使用高精度库 | | 大规模组合归因 | 累积舍入误差 | Kahan 求和;Decimal | > **实践建议**:在量化系统中,尽量使用 `float64`(Python 默认);对精度要求极高的金额计算(如清算对账),使用 `Decimal` 或整数分单位;在数值 Greeks 计算中,遵循 $\epsilon \approx \sqrt{\varepsilon_m} \cdot S$ 的经验法则。 \n> **下一步**:继续学习 [9.2 根求解](./9.2-root-finding)