C++ 标准库 cmath

下面对 C++ 标准库中 <cmath> 头文件所提供的数学函数和工具做一次系统、深入的梳理,包括常量、基本算术、幂/指数/对数、三角/双曲函数、近似与误差函数、浮点分类与其他实用函数,并配以示例与实践建议。


一、概述

  • <cmath>(C 标准库 <math.h> 的 C++ 版本)提供了一系列对标量(整型、浮点型)进行常见数学运算的函数。
  • 从 C++11 开始,新增了一些高精度或特殊用途的数学函数,并在 <cmath> 中以 std:: 名称空间形式暴露。
  • 所有函数通常具有常数时间复杂度 O(1),但底层可能因实现和精度不同略有差异。

二、数学常量与宏

注意:C++11 起,不再标准化 <cmath> 中的宏,推荐使用 <numbers> 中的常量(如 std::numbers::pi)。不过一些实现仍提供以下宏:

含义
M_PI圆周率 π ≈ 3.14159265358979323846
M_E自然常数 e ≈ 2.71828182845904523536
M_SQRT22
其它如 M_LOG2EM_LN2 等

示例(不推荐,视平台支持而定)

#include <cmath>
#include <iostream>
int main() {
    std::cout << "π = " << M_PI << "\n";
}

三、基本算术函数

函数功能原型
std::abs(x)绝对值int/long double abs(int/long double)
std::fabs(x)绝对值(浮点专用)double fabs(double)
std::fmod(x,y)取模(浮点)double fmod(double x, double y)
std::remainder(x,y)IEEE 风格余数double remainder(double x, double y)
std::copysign(x,y)将 y 的符号复制给 xdouble copysign(double x, double y)
#include <cmath>
#include <iostream>

int main() {
    double x = -3.7, y = 2.0;
    std::cout << std::fabs(x)            // 3.7
              << ", fmod(x,y)=" << std::fmod(x,y)  // -1.7
              << ", copysign:" << std::copysign(x,y)  // +3.7
              << "\n";
}

四、幂运算、指数与对数

函数功能
std::pow(x,y)幂 xy
std::sqrt(x)平方根 x
std::cbrt(x) (C++11)立方根 x3
std::exp(x)自然指数ex
std::expm1(x) (C++11)ex−1 的更高精度计算
std::log(x)自然对数 ln⁡x
std::log2(x) (C++11)以2为底的对数
std::log10(x)以10为底的对数
std::log1p(x) (C++11)ln⁡(1+x) 的更高精度计算
#include <cmath>
#include <iostream>

int main() {
    double v = 16.0;
    std::cout << "sqrt=" << std::sqrt(v)
              << ", cbrt=" << std::cbrt(v)
              << ", pow="   << std::pow(v, 0.25)  // 4th root
              << ", expm1(e)=" << std::expm1(1.0)
              << ", log1p(1)=" << std::log1p(1.0)
              << "\n";
}

五、三角函数与反三角函数

函数功能
std::sinstd::cosstd::tan正弦、余弦、正切
std::asinstd::acosstd::atan反正弦、反余弦、反正切
std::atan2(y, x)二参数反正切,返回 arg⁡(x+iy)
std::sinlcosllong double 版本
#include <cmath>
#include <iostream>

int main() {
    double ang = M_PI / 6;  // 30°
    std::cout << "sin=" << std::sin(ang)
              << ", atan2=" << std::atan2(0.5, std::sqrt(3)/2)
              << "\n";  // 两种方式都 ≈ 0.5
}

六、双曲函数与反双曲函数

函数功能
std::sinhstd::coshstd::tanh双曲正弦/余弦/正切
std::asinhstd::acoshstd::atanh反双曲函数
#include <cmath>
#include <iostream>

int main() {
    double x = 1.0;
    std::cout << "sinh=" << std::sinh(x)
              << ", asinh=" << std::asinh(std::sinh(x))
              << "\n";  // ≈ 1.0
}

七、近似与误差函数(C++11 起)

函数功能
std::erf(x)std::erfc(x)高斯误差函数及其互补
std::tgamma(x)伽马函数 Γ(x)
std::lgamma(x)(\ln
std::hypot(x, y, …) (C++11)计算 x2+y2+… 的稳定版本
std::cbrt(x)立方根(已示)
#include <cmath>
#include <iostream>

int main() {
    std::cout << "erf(1)=" << std::erf(1.0)
              << ", erfc(1)=" << std::erfc(1.0)
              << ", gamma(5)=" << std::tgamma(5.0)  // 4! = 24
              << ", hypot(3,4)=" << std::hypot(3.0,4.0)
              << "\n";
}

八、浮点分类与特殊值检测

函数功能
std::isnan(x)判断 NaN
std::isfinite(x)判断有限
std::isinf(x)判断 ±∞
std::fpclassify(x)分类:FP_INFINITE, FP_NAN, FP_ZERO…
#include <cmath>
#include <iostream>

int main() {
    double a = std::sqrt(-1.0);  // NaN
    std::cout << std::boolalpha
              << "isnan=" << std::isnan(a)
              << ", isfinite=" << std::isfinite(a)
              << "\n";
}

九、实践建议

  1. 精度与函数选择
    • 对小增量计算 exp⁡(x)−1 或 ln⁡(1+x) 用 expm1/log1p 可减少舍入误差。
  2. 稳健的距离计算
    • 计算 Euclid 距离时优先 std::hypot,避免中间溢出或下溢。
  3. 避免隐式转换
    • 对于 float 或 long double,显式调用对应重载(sinfsindcoshl…)以获得最佳性能和精度。
  4. 处理特殊值
    • 计算结果可能产生 NaN/∞,在关键路径加检测(std::isnanstd::isfinite)。
  5. 编译器内建 vs 库函数
    • 大多数编译器对标准数学函数做内建优化(内联、向量化),但确认目标平台支持情况,以免性能意外下降。

通过以上对 <cmath> 中所有主要数学函数的全面梳理与示例,帮助你在科学计算、图形渲染、信号处理、统计分析等领域高效、精确地使用标准库的数学功能。祝编码顺利!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注