[学习] C语言数学库函数背后的故事:`double erf(double x)`

C语言数学库函数背后的故事:double erf(double x)

该系列介绍C语言数学库函数上各个函数的数学原理与应用场景,供有兴趣的同学一起参考学习

文章目录

  • C语言数学库函数背后的故事:`double erf(double x)`
    • 函数原型
    • 功能描述
    • 参数说明
    • 数学特性
    • 实现原理
    • 应用场景
        1. 统计学:正态分布概率
        1. 热传导:无限大平板温度分布
        1. 通信理论:误码率计算
        1. 金融工程:期权定价
    • 使用示例
    • 精度与性能
    • 注意事项
    • 扩展应用
        1. 图像处理 - 误差函数滤波器
        1. 机器学习 - GELU激活函数

函数原型

c 复制代码
double erf(double x);

功能描述

erf(x)计算高斯误差函数(Error Function)的值,定义为:
erf(x)=2π∫0xe−t2dterf(x) = \frac{2}{\sqrt{\pi}} \int_{0}^{x} e^{-t^2} dterf(x)=π 2∫0xe−t2dt

该函数描述了一个随机变量落在正态分布均值附近对称区间内的概率。

其函数形状为(蓝色为efr(x),红色为其互补函数(efrc(x) = 1-efr(x)):

参数说明

  • x:输入值,任意实数(取值范围:−∞-\infty−∞到+∞+\infty+∞)
  • 特殊边界行为:
    • erf(0.0)=0.0erf(0.0) = 0.0erf(0.0)=0.0
    • lim⁡x→+∞erf(x)=1.0\lim_{x \to +\infty} erf(x) = 1.0limx→+∞erf(x)=1.0
    • lim⁡x→−∞erf(x)=−1.0\lim_{x \to -\infty} erf(x) = -1.0limx→−∞erf(x)=−1.0

数学特性

  1. 奇函数性质
    erf(−x)=−erf(x)erf(-x) = -erf(x)erf(−x)=−erf(x)

    利用此性质可优化负值计算

  2. 渐进行为

    • 当x→+∞x \to +\inftyx→+∞时:erf(x)≈1−e−x2xπerf(x) \approx 1 - \frac{e^{-x^2}}{x\sqrt{\pi}}erf(x)≈1−xπ e−x2
    • 当x→−∞x \to -\inftyx→−∞时:erf(x)≈−1+e−x2∣x∣πerf(x) \approx -1 + \frac{e^{-x^2}}{|x|\sqrt{\pi}}erf(x)≈−1+∣x∣π e−x2
  3. 与标准正态分布的关系

    标准正态分布的累积分布函数(CDF)可表示为:
    Φ(x)=12[1+erf(x2)]\Phi(x) = \frac{1}{2} \left[1 + erf\left(\frac{x}{\sqrt{2}}\right)\right]Φ(x)=21[1+erf(2 x)]

实现原理

现代数学库通常采用分段逼近策略:

  1. 小∣x∣|x|∣x∣区域 (∣x∣<0.5|x| < 0.5∣x∣<0.5):
    erf(x)≈x⋅(1+a1x2+a2x4+a3x6+a4x8)erf(x) \approx x \cdot (1 + a_1x^2 + a_2x^4 + a_3x^6 + a_4x^8)erf(x)≈x⋅(1+a1x2+a2x4+a3x6+a4x8)

    其中a1−a4a_1-a_4a1−a4为预计算系数

  2. 中∣x∣|x|∣x∣区域 (0.5≤∣x∣<4.00.5 \leq |x| < 4.00.5≤∣x∣<4.0):
    erf(x)≈sign(x)⋅(1−p0+p1x+p2x2+p3x3q0+q1x+q2x2+q3x3)erf(x) \approx sign(x) \cdot \left(1 - \frac{p_0 + p_1x + p_2x^2 + p_3x^3}{q_0 + q_1x + q_2x^2 + q_3x^3}\right)erf(x)≈sign(x)⋅(1−q0+q1x+q2x2+q3x3p0+p1x+p2x2+p3x3)

  3. 大∣x∣|x|∣x∣区域 (∣x∣≥4.0|x| \geq 4.0∣x∣≥4.0):
    erf(x)≈sign(x)⋅(1−e−x2∣x∣π)erf(x) \approx sign(x) \cdot \left(1 - \frac{e^{-x^2}}{|x|\sqrt{\pi}}\right)erf(x)≈sign(x)⋅(1−∣x∣π e−x2)

应用场景

1. 统计学:正态分布概率

计算随机变量落在区间[a,b][a,b][a,b]的概率:
P(a≤X≤b)=12[erf(b−μσ2)−erf(a−μσ2)]P(a \leq X \leq b) = \frac{1}{2} \left[erf\left(\frac{b-\mu}{\sigma\sqrt{2}}\right) - erf\left(\frac{a-\mu}{\sigma\sqrt{2}}\right)\right]P(a≤X≤b)=21[erf(σ2 b−μ)−erf(σ2 a−μ)]

c 复制代码
double normal_probability(double mu, double sigma, double a, double b) {
    double za = (a - mu) / (sigma * M_SQRT2);
    double zb = (b - mu) / (sigma * M_SQRT2);
    return 0.5 * (erf(zb) - erf(za));
}

2. 热传导:无限大平板温度分布

T(x,t)=T0⋅erf(x2αt)T(x,t) = T_0 \cdot erf\left(\frac{x}{2\sqrt{\alpha t}}\right)T(x,t)=T0⋅erf(2αt x)

3. 通信理论:误码率计算

在AWGN信道中的BPSK误码率:
Pb=12erfc(EbN0)P_b = \frac{1}{2} erfc\left(\sqrt{\frac{E_b}{N_0}}\right)Pb=21erfc(N0Eb )

4. 金融工程:期权定价

Black-Scholes模型中的d1d_1d1项:
d1=ln⁡(S/K)+(r+12σ2)TσTd_1 = \frac{\ln(S/K) + (r + \frac{1}{2}\sigma^2)T}{\sigma\sqrt{T}}d1=σT ln(S/K)+(r+21σ2)T

N(d1)=12[1+erf(d12)]N(d_1) = \frac{1}{2} \left[1 + erf\left(\frac{d_1}{\sqrt{2}}\right)\right]N(d1)=21[1+erf(2 d1)]

使用示例

c 复制代码
#include <stdio.h>
#include <math.h>

int main() {
    // 计算erf值及其对应的正态分布CDF
    printf("x\t\terf(x)\t\tΦ(x)\n");
    for(double x = -3.0; x <= 3.0; x += 1.0) {
        double erf_val = erf(x);
        double cdf = 0.5 * (1 + erf(x / M_SQRT2));
        printf("%.1f\t\t%.6f\t%.6f\n", x, erf_val, cdf);
    }
    
    // 热传导应用示例
    double position = 0.1;   // 距离热源位置(m)
    double time = 60.0;      // 时间(s)
    double alpha = 1.5e-5;   // 热扩散系数(m²/s)
    double T0 = 100.0;       // 初始温差(℃)
    
    double temp = T0 * erf(position / (2 * sqrt(alpha * time)));
    printf("\n温度分布: %.2f°C\n", temp);
    
    return 0;
}

输出示例

复制代码
x       erf(x)          Φ(x)
-3.0    -0.999978       0.001350
-2.0    -0.995322       0.022750
-1.0    -0.842701       0.158655
0.0     0.000000        0.500000
1.0     0.842701        0.841345
2.0     0.995322        0.977250
3.0     0.999978        0.998650

温度分布: 73.63°C

精度与性能

  1. 精度:现代实现精度通常<1 ULP(Unit in Last Place)
  2. 性能 :计算复杂度为O(1)O(1)O(1),典型耗时约为exp(x)exp(x)exp(x)的1.5-2倍
  3. 互补函数 :对于大xxx值,建议使用erfc(x)=1−erf(x)erfc(x) = 1 - erf(x)erfc(x)=1−erf(x)避免精度损失

注意事项

  1. 大∣x∣|x|∣x∣值处理 :当∣x∣>26|x|>26∣x∣>26时,结果达到浮点数精度极限
  2. 与erfc关系
    erf(x)=1−erfc(x)erf(x) = 1 - erfc(x)erf(x)=1−erfc(x)
    erfc(x)=1−erf(x)erfc(x) = 1 - erf(x)erfc(x)=1−erf(x)
  3. 数学库链接 :编译时需添加-lm选项(Linux)或链接数学库

扩展应用

1. 图像处理 - 误差函数滤波器

Ifiltered(x,y)=I(x,y)⋅erf(1∥(x,y)−(cx,cy)∥)I_{filtered}(x,y) = I(x,y) \cdot erf\left(\frac{1}{\|(x,y)-(c_x,c_y)\|}\right)Ifiltered(x,y)=I(x,y)⋅erf(∥(x,y)−(cx,cy)∥1)

2. 机器学习 - GELU激活函数

GELU(x)=12x(1+erf(x2))GELU(x) = \frac{1}{2}x\left(1 + erf\left(\frac{x}{\sqrt{2}}\right)\right)GELU(x)=21x(1+erf(2 x))

erf()函数作为概率计算和科学建模的核心工具,其正确使用需要理解其数学本质和数值特性。在实际应用中,应特别注意边界情况和精度要求,必要时使用互补函数erfc()提高计算精度。


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


相关推荐
iCxhust2 小时前
c# U盘映像生成工具
开发语言·单片机·c#
yangzhi_emo3 小时前
ES6笔记2
开发语言·前端·javascript
九年义务漏网鲨鱼3 小时前
【大模型学习 | MINIGPT-4原理】
人工智能·深度学习·学习·语言模型·多模态
emplace_back3 小时前
C# 集合表达式和展开运算符 (..) 详解
开发语言·windows·c#
萧曵 丶4 小时前
Rust 所有权系统:深入浅出指南
开发语言·后端·rust
xiaolang_8616_wjl4 小时前
c++文字游戏_闯关打怪2.0(开源)
开发语言·c++·开源
收破烂的小熊猫~4 小时前
《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
java·开发语言·设计模式
nananaij4 小时前
【Python进阶篇 面向对象程序设计(3) 继承】
开发语言·python·神经网络·pycharm