121 <cmath>数学库
1
Gemini(2.0 Flash Thinking) Prompts:
2
请生成系统性、结构化的学习笔记,要求涵盖各个知识点。关于:c++的库。
3
**内容要求**如下:
4
1. 先写介绍,再写正文,最后做总结。
5
2. 合理使用emoji;
6
3. 不能遗漏任何知识点;
7
4. 对每个API(函数、变量)给出名称、用途、原型、代码、注释;
8
5. 在专业的角度指明最佳实践、常见错误用法、陷阱等;
9
**格式要求**如下:
10
1. **多级标题**:用 `## 1 一级标题` → `### 1.1 二级标题` → `### 1.1.1 三级标题` 的层级编号;
11
2. **单级条目**:所有 `1.` `2.` `3.` 这样的单级列表,改用带圈数字 `①` `②` `③` 表示;
12
3. **禁止使用**:Markdown 的 `-` `*` 无序列表或 `1.` `2.` 有序列表语法;
13
4. 请自动生成层级编号(如 1.1、1.2),无需我手动输入数字。不要大标题,正文从## 1. 开始;
14
5. 在表格或代码块的前后添加空行;
1. <cmath>
库简介 🚀
<cmath>
是 C++ 标准库中的一个头文件,它提供了一组用于执行常见的数学运算的函数。这些函数涵盖了三角函数、指数和对数函数、幂函数、舍入函数以及其他有用的数值操作。使用 <cmath>
库可以方便地在 C++ 程序中进行复杂的数学计算。本学习笔记将系统性地介绍 <cmath>
库中的各个知识点,帮助你更好地理解和使用它。
2. 正文
2.1 数学常数 📌
<cmath>
库定义了一些常用的数学常数,可以通过预定义的宏来访问。
2.1.1 M_PI
① 名称:M_PI
② 用途:表示圆周率 π (约等于 3.14159)。
③ 原型:#define M_PI 3.14159265358979323846
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double radius = 5.0;
6
double circumference = 2 * M_PI * radius;
7
std::cout << "圆的周长为: " << circumference << std::endl;
8
return 0;
9
}
⑤ 注释:这是一个预处理器宏,在编译时会被替换为相应的数值。
2.1.2 M_E
① 名称:M_E
② 用途:表示自然对数的底 e (约等于 2.71828)。
③ 原型:#define M_E 2.71828182845904523536
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::exp(x); // 计算 e 的 x 次方
7
std::cout << "e 的 " << x << " 次方为: " << result << std::endl;
8
return 0;
9
}
⑤ 注释:同样是一个预处理器宏,表示自然对数的底。
2.1.3 M_LOG2E
① 名称:M_LOG2E
② 用途:表示以 2 为底的 e 的对数 (log₂(e)),约等于 1.44269。
③ 原型:#define M_LOG2E 1.44269504088896340736
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "log2(e) 的值为: " << M_LOG2E << std::endl;
6
return 0;
7
}
⑤ 注释:用于将自然对数转换为以 2 为底的对数。
2.1.4 M_LOG10E
① 名称:M_LOG10E
② 用途:表示以 10 为底的 e 的对数 (log₁₀(e)),约等于 0.43429。
③ 原型:#define M_LOG10E 0.43429448190325182765
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "log10(e) 的值为: " << M_LOG10E << std::endl;
6
return 0;
7
}
⑤ 注释:用于将自然对数转换为以 10 为底的对数。
2.1.5 M_LN2
① 名称:M_LN2
② 用途:表示 2 的自然对数 (ln(2)),约等于 0.693147。
③ 原型:#define M_LN2 0.69314718055994530942
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "ln(2) 的值为: " << M_LN2 << std::endl;
6
return 0;
7
}
⑤ 注释:在计算与 2 相关的对数时很有用。
2.1.6 M_LN10
① 名称:M_LN10
② 用途:表示 10 的自然对数 (ln(10)),约等于 2.30259。
③ 原型:#define M_LN10 2.30258509299404568402
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "ln(10) 的值为: " << M_LN10 << std::endl;
6
return 0;
7
}
⑤ 注释:在计算以 10 为底的对数时很有用。
2.1.7 M_PI_2
① 名称:M_PI_2
② 用途:表示 π/2 (约等于 1.57080)。
③ 原型:#define M_PI_2 1.57079632679489661923
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "π/2 的值为: " << M_PI_2 << std::endl;
6
return 0;
7
}
⑤ 注释:常用于三角函数计算。
2.1.8 M_PI_4
① 名称:M_PI_4
② 用途:表示 π/4 (约等于 0.78540)。
③ 原型:#define M_PI_4 0.78539816339744830962
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "π/4 的值为: " << M_PI_4 << std::endl;
6
return 0;
7
}
⑤ 注释:常用于三角函数计算。
2.1.9 M_1_PI
① 名称:M_1_PI
② 用途:表示 1/π (约等于 0.31831)。
③ 原型:#define M_1_PI 0.31830988618379067154
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "1/π 的值为: " << M_1_PI << std::endl;
6
return 0;
7
}
⑤ 注释:用于将角度转换为弧度或进行相关计算。
2.1.10 M_2_PI
① 名称:M_2_PI
② 用途:表示 2/π (约等于 0.63662)。
③ 原型:#define M_2_PI 0.63661977236758134308
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "2/π 的值为: " << M_2_PI << std::endl;
6
return 0;
7
}
⑤ 注释:常用于某些数学公式中。
2.1.11 M_2_SQRTPI
① 名称:M_2_SQRTPI
② 用途:表示 2/√π (约等于 1.12838)。
③ 原型:#define M_2_SQRTPI 1.12837916709551257390
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "2/√π 的值为: " << M_2_SQRTPI << std::endl;
6
return 0;
7
}
⑤ 注释:在某些统计学和概率计算中会用到。
2.1.12 M_SQRT2
① 名称:M_SQRT2
② 用途:表示 √2 (约等于 1.41421)。
③ 原型:#define M_SQRT2 1.41421356237309504880
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "√2 的值为: " << M_SQRT2 << std::endl;
6
return 0;
7
}
⑤ 注释:常见的无理数。
2.1.13 M_SQRT1_2
① 名称:M_SQRT1_2
② 用途:表示 1/√2 (约等于 0.707107)。
③ 原型:#define M_SQRT1_2 0.70710678118654752440
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
std::cout << "1/√2 的值为: " << M_SQRT1_2 << std::endl;
6
return 0;
7
}
⑤ 注释:也常写作 √2 / 2。
最佳实践:直接使用这些预定义的宏可以提高代码的可读性和准确性,避免手动输入近似值可能带来的误差。
常见错误用法:不要尝试修改这些宏的值,因为它们是在编译时确定的。
陷阱:这些宏在不同的编译器和平台上可能不完全相同,虽然标准要求它们具有一定的精度。建议在对精度要求非常高的场景下,查阅具体编译器的文档。
2.2 三角函数 📐
<cmath>
库提供了一系列用于计算三角函数的函数。
2.2.1 std::sin
① 名称:std::sin
② 用途:计算给定角度(以弧度为单位)的正弦值。
③ 原型:
1
double sin(double arg);
2
float sin(float arg);
3
long double sin(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double angle = M_PI / 2.0; // 90 度
6
double sineValue = std::sin(angle);
7
std::cout << "sin(" << angle << ") = " << sineValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须以弧度为单位。
2.2.2 std::cos
① 名称:std::cos
② 用途:计算给定角度(以弧度为单位)的余弦值。
③ 原型:
1
double cos(double arg);
2
float cos(float arg);
3
long double cos(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double angle = 0.0;
6
double cosineValue = std::cos(angle);
7
std::cout << "cos(" << angle << ") = " << cosineValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须以弧度为单位。
2.2.3 std::tan
① 名称:std::tan
② 用途:计算给定角度(以弧度为单位)的正切值。
③ 原型:
1
double tan(double arg);
2
float tan(float arg);
3
long double tan(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double angle = M_PI / 4.0; // 45 度
6
double tangentValue = std::tan(angle);
7
std::cout << "tan(" << angle << ") = " << tangentValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须以弧度为单位。当角度接近 π/2 的奇数倍时,正切值会趋于无穷大。
2.2.4 std::asin
① 名称:std::asin
② 用途:计算给定值的反正弦(弧度值)。返回值范围为 [-π/2, π/2]。
③ 原型:
1
double asin(double arg);
2
float asin(float arg);
3
long double asin(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double value = 1.0;
6
double arcsineValue = std::asin(value);
7
std::cout << "asin(" << value << ") = " << arcsineValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
的取值范围为 [-1, 1]。
2.2.5 std::acos
① 名称:std::acos
② 用途:计算给定值的反余弦(弧度值)。返回值范围为 [0, π]。
③ 原型:
1
double acos(double arg);
2
float acos(float arg);
3
long double acos(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double value = -1.0;
6
double arccosineValue = std::acos(value);
7
std::cout << "acos(" << value << ") = " << arccosineValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
的取值范围为 [-1, 1]。
2.2.6 std::atan
① 名称:std::atan
② 用途:计算给定值的反正切(弧度值)。返回值范围为 [-π/2, π/2]。
③ 原型:
1
double atan(double arg);
2
float atan(float arg);
3
long double atan(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double value = 1.0;
6
double arctangentValue = std::atan(value);
7
std::cout << "atan(" << value << ") = " << arctangentValue << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
可以是任何实数。
2.2.7 std::atan2
① 名称:std::atan2
② 用途:计算 y/x
的反正切(弧度值)。它使用两个参数的符号来确定结果的象限,返回值范围为 [-π, π]。
③ 原型:
1
double atan2(double y, double x);
2
float atan2(float y, float x);
3
long double atan2(long double y, long double x);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double y = 1.0;
6
double x = 1.0;
7
double angle = std::atan2(y, x);
8
std::cout << "atan2(" << y << ", " << x << ") = " << angle << std::endl;
9
return 0;
10
}
⑤ 注释:与 std::atan(y/x)
相比,std::atan2
更稳定,因为它能处理 x
为零的情况,并能正确确定角度的象限。
最佳实践:在进行三角函数计算时,务必确保角度单位是弧度。如果需要使用角度,需要先将其转换为弧度(弧度 = 角度 * π / 180)。使用 std::atan2
而不是 std::atan(y/x)
可以避免除以零的错误,并能提供更准确的角度信息。
常见错误用法:混淆角度和弧度是常见的错误。例如,直接将角度值传递给 std::sin
等函数会导致错误的结果。
陷阱:由于浮点数的精度限制,三角函数的结果可能存在微小的误差。在比较浮点数时,应该使用一个小的容差值(epsilon)。
2.3 双曲函数 🏔️
<cmath>
库提供了一系列用于计算双曲函数的函数。
2.3.1 std::sinh
① 名称:std::sinh
② 用途:计算给定值的双曲正弦值。
③ 原型:
1
double sinh(double arg);
2
float sinh(float arg);
3
long double sinh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::sinh(x);
7
std::cout << "sinh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:sinh(x) = (eˣ - e⁻ˣ) / 2
2.3.2 std::cosh
① 名称:std::cosh
② 用途:计算给定值的双曲余弦值。
③ 原型:
1
double cosh(double arg);
2
float cosh(float arg);
3
long double cosh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::cosh(x);
7
std::cout << "cosh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:cosh(x) = (eˣ + e⁻ˣ) / 2
2.3.3 std::tanh
① 名称:std::tanh
② 用途:计算给定值的双曲正切值。
③ 原型:
1
double tanh(double arg);
2
float tanh(float arg);
3
long double tanh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::tanh(x);
7
std::cout << "tanh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:tanh(x) = sinh(x) / cosh(x) = (eˣ - e⁻ˣ) / (eˣ + e⁻ˣ)
2.3.4 std::asinh
① 名称:std::asinh
② 用途:计算给定值的反双曲正弦值。
③ 原型:
1
double asinh(double arg);
2
float asinh(float arg);
3
long double asinh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::asinh(x);
7
std::cout << "asinh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:也称为 arcsinh
。
2.3.5 std::acosh
① 名称:std::acosh
② 用途:计算给定值的反双曲余弦值。参数 arg
必须大于或等于 1。
③ 原型:
1
double acosh(double arg);
2
float acosh(float arg);
3
long double acosh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 2.0;
6
double result = std::acosh(x);
7
std::cout << "acosh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:也称为 arccosh
。
2.3.6 std::atanh
① 名称:std::atanh
② 用途:计算给定值的反双曲正切值。参数 arg
的绝对值必须小于 1。
③ 原型:
1
double atanh(double arg);
2
float atanh(float arg);
3
long double atanh(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 0.5;
6
double result = std::atanh(x);
7
std::cout << "atanh(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:也称为 arctanh
。
最佳实践:双曲函数在物理学、工程学等领域有广泛应用。理解它们的定义和性质有助于正确使用这些函数。
常见错误用法:std::acosh
和 std::atanh
对输入参数有特定的限制。传递超出范围的参数会导致未定义行为或返回 NaN
。
陷阱:与三角函数类似,双曲函数的结果也可能受到浮点数精度的影响。
2.4 指数和对数函数 📈
<cmath>
库提供了一系列用于计算指数和对数的函数。
2.4.1 std::exp
① 名称:std::exp
② 用途:计算 e 的给定次方 (eˣ)。
③ 原型:
1
double exp(double arg);
2
float exp(float arg);
3
long double exp(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 2.0;
6
double result = std::exp(x);
7
std::cout << "e^" << x << " = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:e
是自然对数的底。
2.4.2 std::expm1
① 名称:std::expm1
② 用途:计算 e 的给定次方减 1 (eˣ - 1)。对于接近零的 x
值,该函数比 std::exp(x) - 1
更精确。
③ 原型:
1
double expm1(double arg);
2
float expm1(float arg);
3
long double expm1(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1e-10;
6
double result1 = std::exp(x) - 1;
7
double result2 = std::expm1(x);
8
std::cout << "exp(" << x << ") - 1 = " << result1 << std::endl;
9
std::cout << "expm1(" << x << ") = " << result2 << std::endl;
10
return 0;
11
}
⑤ 注释:在需要高精度计算且 x
接近零时非常有用。
2.4.3 std::log
① 名称:std::log
② 用途:计算给定值的自然对数(以 e 为底的对数,ln(x))。
③ 原型:
1
double log(double arg);
2
float log(float arg);
3
long double log(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = M_E;
6
double result = std::log(x);
7
std::cout << "ln(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须大于 0。
2.4.4 std::log10
① 名称:std::log10
② 用途:计算给定值的以 10 为底的对数(log₁₀(x))。
③ 原型:
1
double log10(double arg);
2
float log10(float arg);
3
long double log10(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 100.0;
6
double result = std::log10(x);
7
std::cout << "log10(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须大于 0。
2.4.5 std::log1p
① 名称:std::log1p
② 用途:计算 1 加给定值的自然对数 (ln(1 + x))。对于接近零的 x
值,该函数比 std::log(1 + x)
更精确。
③ 原型:
1
double log1p(double arg);
2
float log1p(float arg);
3
long double log1p(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1e-10;
6
double result1 = std::log(1 + x);
7
double result2 = std::log1p(x);
8
std::cout << "log(1 + " << x << ") = " << result1 << std::endl;
9
std::cout << "log1p(" << x << ") = " << result2 << std::endl;
10
return 0;
11
}
⑤ 注释:在需要高精度计算且 x
接近零时非常有用。参数 arg
必须大于 -1。
2.4.6 std::log2
(C++11 起)
① 名称:std::log2
② 用途:计算给定值的以 2 为底的对数(log₂(x))。
③ 原型:
1
double log2(double arg);
2
float log2(float arg);
3
long double log2(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 8.0;
6
double result = std::log2(x);
7
std::cout << "log2(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须大于 0。
最佳实践:根据需要选择合适的对数函数。std::log
用于自然对数,std::log10
用于以 10 为底的对数,std::log2
用于以 2 为底的对数。对于接近零的 x
值,优先使用 std::expm1
和 std::log1p
以提高精度。
常见错误用法:传递非正数给对数函数会导致未定义行为或返回 NaN
.
陷阱:对数函数在参数接近零时变化非常快,需要注意数值稳定性。
2.5 幂函数 ⚡
<cmath>
库提供了一系列用于计算幂的函数。
2.5.1 std::pow
① 名称:std::pow
② 用途:计算底数的指定次方(base^exponent)。
③ 原型:
1
double pow(double base, double exp);
2
float pow(float base, float exp);
3
long double pow(long double base, long double exp);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double base = 2.0;
6
double exponent = 3.0;
7
double result = std::pow(base, exponent);
8
std::cout << base << "^" << exponent << " = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:当底数为负数且指数为非整数时,结果可能是 NaN
。
2.5.2 std::sqrt
① 名称:std::sqrt
② 用途:计算给定值的平方根。
③ 原型:
1
double sqrt(double arg);
2
float sqrt(float arg);
3
long double sqrt(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 16.0;
6
double result = std::sqrt(x);
7
std::cout << "√" << x << " = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
必须是非负数。
2.5.3 std::cbrt
(C++11 起)
① 名称:std::cbrt
② 用途:计算给定值的立方根。
③ 原型:
1
double cbrt(double arg);
2
float cbrt(float arg);
3
long double cbrt(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 27.0;
6
double result = std::cbrt(x);
7
std::cout << "³√" << x << " = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:参数 arg
可以是任何实数。
2.5.4 std::hypot
(C++11 起)
① 名称:std::hypot
② 用途:计算直角三角形的斜边长度,避免了中间计算可能发生的溢出或下溢。计算公式为 √(x² + y²)。
③ 原型:
1
double hypot(double x, double y);
2
float hypot(float x, float y);
3
long double hypot(long double x, long double y);
4
double hypot(double x, double y, double z); // C++17 起
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 3.0;
6
double y = 4.0;
7
double result = std::hypot(x, y);
8
std::cout << "直角三角形斜边长为: " << result << std::endl;
9
return 0;
10
}
⑤ 注释:对于三个参数的版本,计算的是 √(x² + y² + z²)。
最佳实践:使用 std::sqrt
计算平方根,std::cbrt
计算立方根。当需要计算直角三角形斜边时,优先使用 std::hypot
。
常见错误用法:传递负数给 std::sqrt
会导致 NaN
。
陷阱:在计算较大数值的幂时,可能会发生溢出。
2.6 舍入函数 🔢
<cmath>
库提供了一系列用于舍入数值的函数。
2.6.1 std::ceil
① 名称:std::ceil
② 用途:返回不小于给定值的最小整数。向上取整。
③ 原型:
1
double ceil(double arg);
2
float ceil(float arg);
3
long double ceil(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 3.14;
6
double result = std::ceil(x);
7
std::cout << "ceil(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:返回类型与参数类型相同,但表示的是一个整数值。
2.6.2 std::floor
① 名称:std::floor
② 用途:返回不大于给定值的最大整数。向下取整。
③ 原型:
1
double floor(double arg);
2
float floor(float arg);
3
long double floor(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 3.99;
6
double result = std::floor(x);
7
std::cout << "floor(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:返回类型与参数类型相同,但表示的是一个整数值。
2.6.3 std::round
(C++11 起)
① 名称:std::round
② 用途:将给定值四舍五入到最接近的整数。如果小数部分恰好为 0.5,则远离零的方向舍入。
③ 原型:
1
double round(double arg);
2
float round(float arg);
3
long double round(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x1 = 3.5;
6
double x2 = -3.5;
7
double result1 = std::round(x1);
8
double result2 = std::round(x2);
9
std::cout << "round(" << x1 << ") = " << result1 << std::endl;
10
std::cout << "round(" << x2 << ") = " << result2 << std::endl;
11
return 0;
12
}
⑤ 注释:返回类型与参数类型相同,但表示的是一个整数值。
2.6.4 std::trunc
(C++11 起)
① 名称:std::trunc
② 用途:返回给定值的整数部分,即截断小数部分。
③ 原型:
1
double trunc(double arg);
2
float trunc(float arg);
3
long double trunc(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x1 = 3.7;
6
double x2 = -3.7;
7
double result1 = std::trunc(x1);
8
double result2 = std::trunc(x2);
9
std::cout << "trunc(" << x1 << ") = " << result1 << std::endl;
10
std::cout << "trunc(" << x2 << ") = " << result2 << std::endl;
11
return 0;
12
}
⑤ 注释:返回类型与参数类型相同,但表示的是一个整数值。
2.6.5 std::nearbyint
(C++11 起)
① 名称:std::nearbyint
② 用途:将给定值舍入到最接近的整数,舍入方式由当前的浮点舍入模式决定。它不会引发浮点异常。
③ 原型:
1
double nearbyint(double arg);
2
float nearbyint(float arg);
3
long double nearbyint(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
#include <cfenv>
4
5
int main() {
6
std::fesetround(FE_TONEAREST); // 设置舍入到最接近的偶数
7
double x = 3.5;
8
double result = std::nearbyint(x);
9
std::cout << "nearbyint(" << x << ") = " << result << std::endl;
10
return 0;
11
}
⑤ 注释:需要包含 <cfenv>
头文件来控制浮点舍入模式。
2.6.6 std::rint
(C++11 起)
① 名称:std::rint
② 用途:将给定值舍入到最接近的整数,舍入方式由当前的浮点舍入模式决定。可能会引发浮点异常(FE_INEXACT)。
③ 原型:
1
double rint(double arg);
2
float rint(float arg);
3
long double rint(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
#include <cfenv>
4
5
int main() {
6
std::fesetround(FE_TONEAREST);
7
double x = 3.5;
8
double result = std::rint(x);
9
std::cout << "rint(" << x << ") = " << result << std::endl;
10
return 0;
11
}
⑤ 注释:与 std::nearbyint
类似,但可能引发异常。
2.6.7 std::lrint
(C++11 起)
① 名称:std::lrint
② 用途:将给定值舍入到最接近的整数,并返回一个 long int
类型的值。舍入方式由当前的浮点舍入模式决定。
③ 原型:
1
long int lrint(double arg);
2
long int lrint(float arg);
3
long int lrint(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
#include <cfenv>
4
5
int main() {
6
std::fesetround(FE_TONEAREST);
7
double x = 3.5;
8
long int result = std::lrint(x);
9
std::cout << "lrint(" << x << ") = " << result << std::endl;
10
return 0;
11
}
⑤ 注释:返回 long int
类型。
2.6.8 std::llrint
(C++11 起)
① 名称:std::llrint
② 用途:将给定值舍入到最接近的整数,并返回一个 long long int
类型的值。舍入方式由当前的浮点舍入模式决定。
③ 原型:
1
long long int llrint(double arg);
2
long long int llrint(float arg);
3
long long int llrint(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
#include <cfenv>
4
5
int main() {
6
std::fesetround(FE_TONEAREST);
7
double x = 3.5;
8
long long int result = std::llrint(x);
9
std::cout << "llrint(" << x << ") = " << result << std::endl;
10
return 0;
11
}
⑤ 注释:返回 long long int
类型。
2.6.9 std::lround
(C++11 起)
① 名称:std::lround
② 用途:将给定值四舍五入到最接近的整数,并返回一个 long int
类型的值。如果小数部分恰好为 0.5,则远离零的方向舍入。
③ 原型:
1
long int lround(double arg);
2
long int lround(float arg);
3
long int lround(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x1 = 3.5;
6
double x2 = -3.5;
7
long int result1 = std::lround(x1);
8
long int result2 = std::lround(x2);
9
std::cout << "lround(" << x1 << ") = " << result1 << std::endl;
10
std::cout << "lround(" << x2 << ") = " << result2 << std::endl;
11
return 0;
12
}
⑤ 注释:返回 long int
类型。
2.6.10 std::llround
(C++11 起)
① 名称:std::llround
② 用途:将给定值四舍五入到最接近的整数,并返回一个 long long int
类型的值。如果小数部分恰好为 0.5,则远离零的方向舍入。
③ 原型:
1
long long int llround(double arg);
2
long long int llround(float arg);
3
long long int llround(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x1 = 3.5;
6
double x2 = -3.5;
7
long long int result1 = std::llround(x1);
8
long long int result2 = std::llround(x2);
9
std::cout << "llround(" << x1 << ") = " << result1 << std::endl;
10
std::cout << "llround(" << x2 << ") = " << result2 << std::endl;
11
return 0;
12
}
⑤ 注释:返回 long long int
类型。
最佳实践:根据需要的舍入方式选择合适的函数。std::ceil
向上取整,std::floor
向下取整,std::round
四舍五入(远离零),std::trunc
截断小数部分。std::nearbyint
和 std::rint
受浮点舍入模式影响。std::lround
和 std::llround
返回整数类型。
常见错误用法:混淆不同舍入函数的行为。例如,期望 std::round(3.5)
返回 3,但实际上它返回 4。
陷阱:浮点数的表示方式可能导致一些意想不到的舍入结果。
2.7 绝对值、符号和余数函数 ➕➖
<cmath>
库提供了一些用于处理数值的绝对值、符号和余数的函数。
2.7.1 std::fabs
① 名称:std::fabs
② 用途:计算给定浮点数的绝对值。
③ 原型:
1
double fabs(double arg);
2
float fabs(float arg);
3
long double fabs(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = -3.14;
6
double result = std::fabs(x);
7
std::cout << "| " << x << " | = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:与 std::abs
不同,std::fabs
专门用于浮点数类型。
2.7.2 std::fmod
① 名称:std::fmod
② 用途:计算 x
除以 y
的浮点余数。结果的符号与 x
相同。
③ 原型:
1
double fmod(double x, double y);
2
float fmod(float x, float y);
3
long double fmod(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 10.5;
6
double y = 3.0;
7
double result = std::fmod(x, y);
8
std::cout << "fmod(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:当 y
为零时,结果是未定义的。
2.7.3 std::remainder
(C++11 起)
① 名称:std::remainder
② 用途:计算 x
除以 y
的浮点余数。结果的符号可能与 x
不同,其绝对值总是小于或等于 y
的绝对值的一半。
③ 原型:
1
double remainder(double x, double y);
2
float remainder(float x, float y);
3
long double remainder(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 10.5;
6
double y = 3.0;
7
double result = std::remainder(x, y);
8
std::cout << "remainder(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:与 std::fmod
的行为略有不同,尤其是在处理负数时。
2.7.4 std::div
(在 <cstdlib>
中定义,但常与 <cmath>
一起讨论)
① 名称:std::div
② 用途:计算整数除法的商和余数。返回一个 div_t
结构体,包含 quot
(商)和 rem
(余数)成员。
③ 原型:
1
div_t div(int numer, int denom);
2
ldiv_t div(long int numer, long int denom);
3
lldiv_t div(long long int numer, long long int denom); // C++11 起
④ 代码:
1
#include <iostream>
2
#include <cstdlib>
3
4
int main() {
5
int numerator = 10;
6
int denominator = 3;
7
std::div_t result = std::div(numerator, denominator);
8
std::cout << "商: " << result.quot << ", 余数: " << result.rem << std::endl;
9
return 0;
10
}
⑤ 注释:虽然在 <cstdlib>
中定义,但在进行数值计算时也很有用。
2.7.5 std::fdim
(C++11 起)
① 名称:std::fdim
② 用途:计算 max(x - y, 0)
。
③ 原型:
1
double fdim(double x, double y);
2
float fdim(float x, float y);
3
long double fdim(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 5.0;
6
double y = 2.0;
7
double result = std::fdim(x, y);
8
std::cout << "fdim(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:常用于计算两个值之间的正差。
2.7.6 std::fmax
(C++11 起)
① 名称:std::fmax
② 用途:返回两个浮点数中的较大值。
③ 原型:
1
double fmax(double x, double y);
2
float fmax(float x, float y);
3
long double fmax(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 5.0;
6
double y = 2.0;
7
double result = std::fmax(x, y);
8
std::cout << "fmax(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:与使用 >
运算符相比,std::fmax
在处理 NaN
时有特定的行为(通常返回非 NaN
的值,如果两个都是 NaN
则返回 NaN
)。
2.7.7 std::fmin
(C++11 起)
① 名称:std::fmin
② 用途:返回两个浮点数中的较小值。
③ 原型:
1
double fmin(double x, double y);
2
float fmin(float x, float y);
3
long double fmin(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 5.0;
6
double y = 2.0;
7
double result = std::fmin(x, y);
8
std::cout << "fmin(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:与使用 <
运算符相比,std::fmin
在处理 NaN
时有特定的行为。
2.7.8 std::copysign
(C++11 起)
① 名称:std::copysign
② 用途:返回一个数值,其大小与第一个参数相同,符号与第二个参数相同。
③ 原型:
1
double copysign(double x, double y);
2
float copysign(float x, float y);
3
long double copysign(long double x, long double y);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = -5.0;
6
double y = 2.0;
7
double result = std::copysign(x, y);
8
std::cout << "copysign(" << x << ", " << y << ") = " << result << std::endl;
9
return 0;
10
}
⑤ 注释:常用于需要保持数值大小但改变符号的场景。
最佳实践:使用 std::fabs
获取浮点数的绝对值。使用 std::fmod
计算浮点余数,注意其与 std::remainder
的区别。std::fmax
和 std::fmin
在处理 NaN
时比直接使用比较运算符更安全。
常见错误用法:混淆 std::fmod
和 std::remainder
的行为,尤其是在处理负数时。
陷阱:当除数为零时,std::fmod
的行为是未定义的。
2.8 浮点数分类函数 (C++11 起) 🤔
<cmath>
库提供了一些用于对浮点数进行分类的函数。
2.8.1 std::fpclassify
① 名称:std::fpclassify
② 用途:返回一个整数值,表示浮点数 arg
的分类。可能的返回值包括:FP_NORMAL
(正常)、FP_SUBNORMAL
(次正规)、FP_ZERO
(零)、FP_INFINITE
(无穷大)、FP_NAN
(非数值)。
③ 原型:
1
int fpclassify(double arg);
2
int fpclassify(float arg);
3
int fpclassify(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 0.0;
6
int classification = std::fpclassify(x);
7
if (classification == FP_ZERO) {
8
std::cout << x << " 是零" << std::endl;
9
}
10
return 0;
11
}
⑤ 注释:需要包含 <cmath>
头文件才能使用 FP_*
宏。
2.8.2 std::isfinite
① 名称:std::isfinite
② 用途:检查给定的浮点数是否是有限的(既不是无穷大也不是 NaN
)。
③ 原型:
1
bool isfinite(double arg);
2
bool isfinite(float arg);
3
bool isfinite(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0 / 0.0; // 无穷大
6
if (std::isfinite(x)) {
7
std::cout << x << " 是有限的" << std::endl;
8
} else {
9
std::cout << x << " 不是有限的" << std::endl;
10
}
11
return 0;
12
}
⑤ 注释:返回 true
如果参数是有限的,否则返回 false
。
2.8.3 std::isinf
① 名称:std::isinf
② 用途:检查给定的浮点数是否是无穷大(正无穷大或负无穷大)。
③ 原型:
1
bool isinf(double arg);
2
bool isinf(float arg);
3
bool isinf(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0 / 0.0;
6
if (std::isinf(x)) {
7
std::cout << x << " 是无穷大" << std::endl;
8
}
9
return 0;
10
}
⑤ 注释:返回 true
如果参数是无穷大,否则返回 false
。
2.8.4 std::isnan
① 名称:std::isnan
② 用途:检查给定的浮点数是否是 NaN
(非数值)。
③ 原型:
1
bool isnan(double arg);
2
bool isnan(float arg);
3
bool isnan(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = std::sqrt(-1.0);
6
if (std::isnan(x)) {
7
std::cout << x << " 是 NaN" << std::endl;
8
}
9
return 0;
10
}
⑤ 注释:返回 true
如果参数是 NaN
,否则返回 false
。
2.8.5 std::isnormal
(C++11 起)
① 名称:std::isnormal
② 用途:检查给定的浮点数是否是正常的(既不是零、次正规、无穷大也不是 NaN
)。
③ 原型:
1
bool isnormal(double arg);
2
bool isnormal(float arg);
3
bool isnormal(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
if (std::isnormal(x)) {
7
std::cout << x << " 是正常的" << std::endl;
8
}
9
return 0;
10
}
⑤ 注释:返回 true
如果参数是正常的,否则返回 false
。
2.8.6 std::signbit
(C++11 起)
① 名称:std::signbit
② 用途:检查给定的浮点数是否具有负符号。
③ 原型:
1
bool signbit(double arg);
2
bool signbit(float arg);
3
bool signbit(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = -3.14;
6
if (std::signbit(x)) {
7
std::cout << x << " 是负数" << std::endl;
8
}
9
return 0;
10
}
⑤ 注释:返回 true
如果参数是负数(包括负零),否则返回 false
。
最佳实践:在进行浮点数运算时,经常需要检查结果是否为 NaN
或无穷大。使用这些分类函数可以帮助编写更健壮的代码。
常见错误用法:不要直接使用 ==
运算符来比较浮点数是否等于 NaN
,应该使用 std::isnan
。
陷阱:浮点数的行为可能与直觉不同,特别是在涉及无穷大和 NaN
时。
2.9 其他数学函数 ➕➖✖️➗
<cmath>
库还提供了一些其他的数学函数。
2.9.1 std::erf
(C++11 起)
① 名称:std::erf
② 用途:计算高斯误差函数。
③ 原型:
1
double erf(double arg);
2
float erf(float arg);
3
long double erf(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 1.0;
6
double result = std::erf(x);
7
std::cout << "erf(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:误差函数在概率、统计和偏微分方程等领域有应用。
2.9.2 std::erfc
(C++11 起)
① 名称:std::erfc
② 用途:计算互补高斯误差函数,即 1 - erf(arg)
。对于较大的 arg
值,该函数比 1.0 - std::erf(arg)
更精确。
③ 原型:
1
double erfc(double arg);
2
float erfc(float arg);
3
long double erfc(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 2.0;
6
double result = std::erfc(x);
7
std::cout << "erfc(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:在需要高精度计算且 arg
较大时很有用。
2.9.3 std::tgamma
(C++11 起)
① 名称:std::tgamma
② 用途:计算伽马函数。
③ 原型:
1
double tgamma(double arg);
2
float tgamma(float arg);
3
long double tgamma(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 3.0;
6
double result = std::tgamma(x); // 伽马函数在整数点上的值为 (n-1)!
7
std::cout << "tgamma(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:伽马函数是阶乘函数在复数域上的推广。
2.9.4 std::lgamma
(C++11 起)
① 名称:std::lgamma
② 用途:计算伽马函数的绝对值的自然对数。
③ 原型:
1
double lgamma(double arg);
2
float lgamma(float arg);
3
long double lgamma(long double arg);
④ 代码:
1
#include <iostream>
2
#include <cmath>
3
4
int main() {
5
double x = 3.0;
6
double result = std::lgamma(x);
7
std::cout << "lgamma(" << x << ") = " << result << std::endl;
8
return 0;
9
}
⑤ 注释:在计算伽马函数时,为了避免溢出,通常计算其对数值。
3. 总结 ✅
<cmath>
库是 C++ 中进行数学计算的重要工具,它提供了丰富的函数和常量,涵盖了三角函数、指数和对数函数、幂函数、舍入函数以及其他数值操作。理解每个函数的用途、原型和注意事项,并掌握最佳实践和常见错误用法,能够帮助我们编写更高效、更准确的数值计算程序。在实际应用中,应根据具体需求选择合适的函数,并注意浮点数的精度问题和潜在的陷阱。希望这份系统性的学习笔记能够帮助你更好地掌握 <cmath>
库的使用。
```