C++中复数的处理与应用
立即解锁
发布时间: 2025-08-22 00:43:55 阅读量: 1 订阅数: 16 


深入解析C++标准库:从入门到精通
### C++ 中复数的处理与应用
#### 1. 复数概述
复数由实部和虚部组成,虚部的平方为负数,虚部的因子 $i$ 是 -1 的平方根。C++ 标准库提供了类模板 `complex<>` 来操作复数。C++98 几乎规定了 `complex<>` 类的所有特性,C++11 仅进行了一些修复和增强:
- 新增了以复数为参数的操作,如 `proj()`、`asin()`、`acos()`、`atan()`、`asinh()`、`acosh()`、`atanh()`。
- 可以使用 `real(val)` 和 `imag(val)` 直接设置实部和虚部。
#### 2. `complex<>` 类的一般情况
`complex<>` 类在头文件 `<complex>` 中声明:
```cpp
#include <complex>
namespace std {
template <typename T>
class complex;
}
```
模板参数 `T` 用作复数实部和虚部的标量类型。此外,C++ 标准库为 `float`、`double` 和 `long double` 提供了三种特化:
```cpp
namespace std {
template<> class complex<float>;
template<> class complex<double>;
template<> class complex<long double>;
}
```
这些特化允许进行某些优化和更安全的复数类型转换。
#### 3. `complex<>` 类的使用示例
以下是一个使用 `complex<>` 类创建复数、打印不同表示形式并执行常见操作的示例程序:
```cpp
// num/complex1.cpp
#include <iostream>
#include <complex>
using namespace std;
int main()
{
// 具有实部和虚部的复数
// - 实部: 4.0
// - 虚部: 3.0
complex<double> c1(4.0,3.0);
// 从极坐标创建复数
// - 模: 5.0
// - 相角: 0.75
complex<float> c2(polar(5.0,0.75));
// 打印具有实部和虚部的复数
cout << "c1: " << c1 << endl;
cout << "c2: " << c2 << endl;
// 以极坐标形式打印复数
cout << "c1: magnitude: " << abs(c1)
<< " (squared magnitude: " << norm(c1) << ") "
<< " phase angle: " << arg(c1) << endl;
cout << "c2: magnitude: " << abs(c2)
<< " (squared magnitude: " << norm(c2) << ") "
<< " phase angle: " << arg(c2) << endl;
// 打印共轭复数
cout << "c1 conjugated: " << conj(c1) << endl;
cout << "c2 conjugated: " << conj(c2) << endl;
// 打印计算结果
cout << "4.4 + c1 * 1.8: " << 4.4 + c1 * 1.8 << endl;
// 打印 c1 和 c2 的和
// - 注意: 不同类型
cout << "c1 + c2: "
<< c1 + complex<double>(c2.real(),c2.imag()) << endl;
// 将 c1 的平方根加到 c1 并打印结果
cout << "c1 += sqrt(c1): " << (c1 += sqrt(c1)) << endl;
}
```
该程序的输出可能如下(确切输出取决于 `double` 类型的具体实现特性):
```plaintext
c1: (4,3)
c2: (3.65844,3.40819)
c1: magnitude: 5 (squared magnitude: 25) phase angle: 0.643501
c2: magnitude: 5 (squared magnitude: 25) phase angle: 0.75
c1 conjugated: (4,-3)
c2 conjugated: (3.65844,-3.40819)
4.4 + c1 * 1.8: (11.6,5.4)
c1 + c2: (7.65844,6.40819)
c1 += sqrt(c1): (6.12132,3.70711)
```
另一个示例包含一个循环,用于读取两个复数并处理第一个复数的第二个复数次幂:
```cpp
// num/complex2.cpp
#include <iostream>
#include <complex>
#include <cstdlib>
#include <limits>
using namespace std;
int main()
{
complex<long double> c1, c2;
while (cin.peek() != EOF) {
// 读取第一个复数
cout << "complex number c1: ";
cin >> c1;
if (!cin) {
cerr << "input error" << endl;
return EXIT_FAILURE;
}
// 读取第二个复数
cout << "complex number c2: ";
cin >> c2;
if (!cin) {
cerr << "input error" << endl;
return EXIT_FAILURE;
}
if (c1 == c2) {
cout << "c1 and c2 are equal !" << endl;
}
cout << "c1 raised to the c2: " << pow(c1,c2)
<< endl << endl;
// 跳过行的其余部分
cin.ignore(numeric_limits<int>::max(),'\n');
}
}
```
以下是该程序的一些可能输入和输出:
| c1 | c2 | Output |
| --- | --- | --- |
| 2 | 2 | c1 raised to c2: (4,0) |
| (16) | 0.5 | c1 raised to c2: (4,0) |
| (8,0) | 0.333333333 | c1 raised to c2: (2,0) |
| 0.99 | (5) | c1 raised to c2: (0.95099,0) |
| (0,2) | 2 | c1 raised to c2: (-4,4.89843e-16) |
| (1.7,0.3) | 0 | c1 raised to c2: (1,0) |
| (3,4) | (-4,3) | c1 raised to c2: (4.32424e-05,8.91396e-05) |
| (1.7,0.3) | (4.3,2.8) | c1 raised to c2: (-4.17622,4.86871) |
#### 4. 复数的操作
##### 4.1 创建、复制和赋值操作
| 表达式 | 效果 |
| --- | --- |
| `complex c` | 创建一个实部和虚部都为 0 的复数 (0 + 0i) |
| `complex c(1.3)` | 创建一个实部为 1.3,虚部为 0 的复数 (1.3 + 0i) |
| `complex c(1.3,4.2)` | 创建一个实部为 1.3,虚部为 4.2 的复数 (1.3 + 4.2i) |
| `complex c1(c2)` | 创建 c1 作为 c2 的副本 |
| `polar(4.2)` | 从极坐标创建一个临时复数(模为 4.2,相角为 0) |
| `polar(4.2,0.75)` | 从极坐标创建一个临时复数(模为 4.2,相角为 0.75) |
| `conj(c)` | 创建一个 c 的共轭复数(虚部取反) |
| `proj(c)` | 创建一个 c 在黎曼球面上的投影的临时复数(C++11 起) |
| `c1 = c2` | 将 c2 的值赋给 c1 |
| `c1 += c2` | 将 c2 的值加到 c1 |
| `c1 -= c2` | 从 c1 中减去 c2 的值 |
| `c1 *= c2` | 将 c1 乘以 c2 的值 |
| `c1 /= c2` | 将 c1 除以 c2 的值 |
赋值运算符是修改现有复数的唯一方法。辅助函数 `polar()` 允许从极坐标创建复数,但在创建过程中存在隐式类型转换问题。例如:
```cpp
std::complex<float> c2(std::polar(4.2,0.75)); // OK
std::complex<float> c2 = std::polar(4.2,0.75); // ERROR
```
辅助函数 `conj()` 用于创建另一个复数的共轭复数,`proj()` 函数(C++11 起)用于创建一个复数在黎曼球面上的投影。
##### 4.2 隐式类型转换
`float`、`double` 和 `long double` 的特化构造函数设计为允许安全的隐式转换,如 `complex<float>` 到 `complex<double>`,但不安全的转换,如 `complex<long double>` 到 `complex<double>`,必须显式进行:
```cpp
std::complex<float> cf;
std::complex<double> cd;
std::complex<long double> cld;
std::complex<double> cd1
```
0
0
复制全文
相关推荐






