# libm 的函数逼近与工程实现

[[MCS/day6/00 学习指南|day6 学习指南]] · [[MCS/00 MCS学习总览|十一天总览]] · [[MCS/day6/阅读核验与疑问|阅读核验与疑问]] · 上一篇：[[MCS/day6/05 牛顿迭代、不动点与二循环|牛顿迭代、不动点与二循环]] · 下一篇：[[MCS/day6/07 牛顿法与梯度下降的完整比较|牛顿法与梯度下降的完整比较]]

> 来源：[[MCS/day6补充2|day6补充2]]。用途：选学。原有推导、追问与解答保留；阅读时请结合本日核验说明。

## libm 底层：泰勒展开 + 优化（CORDIC 算法、切比雪夫多项式）

### 1. libm 是什么

**libm = lib mathematics**，就是 C 标准库里的数学库。

你写 C 代码时：

    #include <math.h>
    double y = sin(x);

这个 `sin` 最终就是链接到 libm 里的实现。**CPU 本身并不"会"算 sin**，是 libm 提供了这些函数的软件实现。

---

### 2. 为什么底层要用"泰勒展开"

CPU 硬件只直接支持 **加减乘除**（以及一些芯片上的 `sqrt`、`FMA` 等）。像 `sin`、`cos`、`exp`、`log` 这种**超越函数**，硬件没有直接指令，只能靠软件算。

数学上有个工具叫**泰勒展开（Taylor series）**，可以把这些函数写成无穷多项的多项式：

    sin(x) = x - x³/3! + x⁵/5! - x⁷/7! + ...
    exp(x) = 1 + x + x²/2! + x³/3! + ...

多项式只有 **加、减、乘**，CPU 完全能做。所以理论上，只要取足够多项，就能把 `sin(x)` 算到任意精度。

---

### 3. 为什么还要"加优化"

如果直接用泰勒展开，会有几个问题：

| 问题 | 说明 |
|------|------|
| 收敛慢 | `x` 很大时，泰勒展开要很多很多项才能收敛，太慢 |
| 精度损失 | `x` 大时高阶项巨大，浮点数相减会丢精度（灾难性抵消） |
| 效率低 | 直接算高次幂很浪费 |

所以实际 libm 里会做很多优化：

#### 3.1 范围规约（Argument Reduction）

比如算 `sin(x)` 时，先用周期性把 `x` 缩到 `[-π/4, π/4]` 这种小范围，小范围里泰勒几项就够准。

#### 3.2 用 minimax 多项式 / 切比雪夫逼近代替纯泰勒

在给定区间内，让**最大误差最小**的多项式，比泰勒截断更省项、更准。

#### 3.3 查表 + 多项式结合

有些实现会先查表取近似值，再用多项式修正。

#### 3.4 利用浮点特性

用 **FMA（乘加融合）** 指令、**Horner 法（秦九韶算法）** 减少运算次数和误差。

#### 3.5 CORDIC 算法

**CORDIC（Coordinate Rotation Digital Computer）** 是一种只用**加法、移位**就能计算三角函数、双曲函数、开方等的迭代算法，特别适合没有硬件乘法器的嵌入式芯片。它通过一系列预定义角度的旋转逼近目标角度，每次迭代只做移位和加减。

---

### 4. 一句话总结

> libm 算 `sin/cos/exp` 这些函数时，硬件只会加减乘除，所以用**泰勒展开**把函数变成多项式来算；但纯泰勒太慢、精度差，于是又做了**范围规约、minimax 逼近、查表、Horner 法**等优化，让结果又快又准。

具体实现 =

**特殊值处理 + 参数规约（Cody-Waite / Payne-Hanek）+ minimax 多项式（Horner + FMA）+ 象限符号调整**

泰勒只提供了"用多项式逼近"这个思想，真正跑在 CPU 上的是经过**误差优化**和**范围规约**的工程版本。

---

### 5. 示例：`Math.sin(0.3)` 的完整流程

以 `Math.sin(0.3)` 为例，libm 内部大致经历以下步骤：

1. **特殊值处理**：检查 `0.3` 是否为 `NaN`、`Inf`、`0` 等，不是则继续。
2. **参数规约**：`0.3` 本身已在 `[-π/4, π/4]` 范围内，无需大幅规约（若输入很大，会用 Cody-Waite 或 Payne-Hanek 算法缩减）。
3. **多项式逼近**：用 minimax 多项式（Horner 法 + FMA）计算 `sin(0.3)`。
4. **象限调整**：根据规约后的象限，决定是否取负或转成 `cos`。
5. **返回结果**：约 `0.29552020666133955`。

---

### 6. 知识图谱

    libm
    ├── 硬件能力：加减乘除 + sqrt + FMA
    ├── 数学基础：泰勒展开
    │   └── 思想：用多项式逼近超越函数
    ├── 工程优化
    │   ├── 范围规约：Cody-Waite / Payne-Hanek
    │   ├── 多项式逼近：minimax / 切比雪夫
    │   ├── 算法：Horner 法、FMA
    │   ├── 查表法
    │   └── CORDIC 算法
    └── 最终实现 = 特殊值处理 + 参数规约 + minimax 多项式 + 象限符号调整
