以下对 C++ 标准库中 <complex>
头文件所提供的复数类型与相关函数做一次系统、深入的梳理,包括类型定义、成员函数、全局操作、转换与输入/输出示例,以及实践建议。
一、概述
<complex>
定义了一个模板类 std::complex<T>
,用于表示实部和虚部均为浮点类型 T
(通常为 float
、double
或 long double
)的复数。
- 除了对复数进行基本算术运算外,还提供了绝对值、相位、指数/对数、三角与双曲函数、共轭等一系列数学函数。
- 所有操作均在复数数学的框架下进行,且在不同精度类型间具有良好的模板通用性。
二、std::complex<T>
类模板
template< class T >
class complex {
public:
// ——— 构造与赋值 ———
constexpr complex( const T& re = T(), const T& im = T() );
template<class U> constexpr complex( const complex<U>& );
// ——— 访问成员 ———
constexpr T real() const; // 实部
constexpr T imag() const; // 虚部
void real( const T& value ); // 设定实部
void imag( const T& value ); // 设定虚部
// ——— 运算符重载 ———
complex& operator+=( const complex& );
complex& operator-=( const complex& );
complex& operator*=( const complex& );
complex& operator/=( const complex& );
};
- 构造
complex<> c;
构造 0+0i
complex<> c(3.0,4.0);
构造 3+4i
- 支持不同精度的隐式拷贝,如
complex<double> cd = complex<float>(1.0f,2.0f);
- 成员访问
c.real()
/ c.imag()
分别返回实部和虚部
- 可通过
c.real(5.0)
修改实部
- 复合赋值
c1 += c2
等效于 c1 = c1 + c2
,其余 -=
、*=
、/=
类似
三、全局算术与比较运算符
// 二元算术
template<class T> complex<T> operator+( const complex<T>&, const complex<T>& );
template<class T> complex<T> operator-( ... );
template<class T> complex<T> operator*( ... );
template<class T> complex<T> operator/( ... );
// 复数与实数混合运算
template<class T> complex<T> operator+( const complex<T>&, const T& );
template<class T> complex<T> operator+( const T&, const complex<T>& );
// 其它 -,*,/ 同理
// 一元运算
template<class T> complex<T> operator-( const complex<T>& ); // 取负
// 比较(C++20 起)
template<class T> bool operator==( const complex<T>&, const complex<T>& );
template<class T> bool operator!=( ... );
- 所有运算遵循复数四则规则,如(a+bi)×(c+di)=(ac−bd) + (ad+bc) i
- 注意:旧标准中未定义复数比较运算;C++20 起可直接用
==
/!=
比较实部和虚部是否分别相等。
四、常用数学函数
1. 基本函数
函数 | 描述 |
---|
std::conj(z) | 共轭:实部不变,虚部取反 |
std::real(z) / std::imag(z) | 非成员版访问实部/虚部 |
std::abs(z) | 复数模长 a2+b2 |
std::arg(z) | 复数幅角 \atan2(b,a) |
std::norm(z) | 模长平方 a2+b2(返回实数类型) |
std::proj(z) (C++11+) | 投影到 Riemann 球面,处理无穷大和 NaN 情形 |
2. 指数与对数
函数 | 描述 |
---|
std::exp(z) | 复指数函数 ez |
std::log(z) | 自然对数 lnz |
std::log10(z) | 常用对数 log10z |
std::pow(z, w) | 幂运算 zw |
3. 三角与双曲函数
函数 | 描述 |
---|
std::sin(z) / std::cos(z) | 正弦 / 余弦 |
std::tan(z) | 正切 |
std::sinh(z) / std::cosh(z) | 双曲正弦 / 双曲余弦 |
std::tanh(z) | 双曲正切 |
反函数:std::asin(z) 、acos(z) 、atan(z) 、asinh(z) 等同理 | |
五、输入/输出支持
#include <complex>
#include <iostream>
int main() {
std::complex<double> z;
std::cin >> z; // 从输入流读取两数,格式:real imag
std::cout << z; // 输出格式: (real,imag)
}
- 格式化
- 默认输出形如
(a,b)
,其中 a 为实部,b 为虚部
- 读取时,会消费括号及逗号,可与流操纵符组合控制格式
六、示例:综合运用
#include <complex>
#include <iostream>
#include <vector>
#include <numeric>
int main() {
// 构造一个复数向量
std::vector<std::complex<double>> v;
for (int k = 0; k < 8; ++k) {
// 生成单位圆上等分点
double theta = 2.0 * M_PI * k / 8;
v.emplace_back(std::polar(1.0, theta));
}
// 计算所有共轭之和
auto conj_sum = std::accumulate(
v.begin(), v.end(),
std::complex<double>{0,0},
[](auto a, auto b){ return a + std::conj(b); }
);
std::cout << "Sum of conjugates: " << conj_sum << "\n";
// 计算第一个元素的模长与幅角
auto z0 = v.front();
std::cout << "abs = " << std::abs(z0)
<< ", arg = " << std::arg(z0) << "\n";
}
std::polar(r, θ)
:根据极坐标构造复数 r (cosθ+isinθ)
- 利用
<numeric>
中的 std::accumulate
、std::conj
等函数完成批量运算
七、实践建议
- 选择合适的底层类型
- 对于标准科学计算,
double
足够;对高精度或数值稳定性要求极高场景可考虑 long double
。
- 注意数值稳定性
std::norm
而非 std::abs
平方:前者避免一次开方,若只需模长平方推荐用 norm
。
- 当实部或虚部远大于另一分量时,
std::abs
可能出现溢出/下溢,可考虑手动缩放或专门算法。
- 使用
std::polar
/ std::arg
完成极坐标转换
- 在信号处理、频域分析(如 FFT)中,经常需要从直角坐标与极坐标互转。
- 避免不必要的临时对象
- 复数表达式可能产生临时,多层链式运算时注意编译器优化。
- 对性能敏感环节,可使用
operator+=
等复合赋值减少拷贝。
- 结合并行与向量化
- C++17 起可将复数容器与并行算法(
std::for_each(std::execution::par,…)
)结合,加速批量运算;但要确保函数无数据竞争。
通过以上对 <complex>
头文件中 std::complex
模板、算术运算、数学函数与 I/O 支持的全面讲解,希冀帮助你在数值计算、信号处理、物理建模等领域高效、正确地使用标准库复数功能。祝编码顺利!