【STL】复数

  |  

摘要: 本文介绍在 C++ STL 中,复数的使用方法

【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings


本文介绍在 C++ STL 中,复数的使用方法。《C++标准库》 第2版,作者 Nicolai M. josuttis,侯捷 译 $17.2。最后用 STL 的复数组件解决力扣第 537 题。


$0 复数

含有两部分,实部和虚部。虚部的特点是平方和为 -1。

$1 class complex<>

1
#include <complex>

其中 class complex 的定义如下:模板参数为实部和虚部的标量类型。

1
2
3
4
namespace std {
template <typename T>
class complex;
}

此外标准库还提供了针对标量类型 float, double, long double 的特化版本。

1
2
3
4
5
namespace std {
template<> class complex<float>;
template<> class complex<double>;
template<> class complex<long double>;
}

$2 复数各项操作

class complex<> 的接口细节,可以参考 《C++标准库》 $17-2-4。下面是一些基础的用法。

创建,复制

1
2
3
4
5
6
7
8
complex c               实部 0,虚部 0
complex c(1.3) 实部 1.3,虚部 0
complex c(1.3, 4.2) 实部 1.3,虚部 4.2
complex c1(c2) 拷贝构造,注意隐式转换的问题
polar(4.2) 极坐标表示法的临时复数,大小 4.2,相角 0
polar(4.2, 0.75) 极坐标表示法的临时复数,大小 4.2,相角 0.75
conj(c) c 的共轭复数
proj(c) c 在黎曼球面的投影

赋值

1
2
3
4
5
c1 = c2
c1 += c2
c1 -= c2
c1 *= c2
c1 /= c2

隐式类型转换

复数的 float, double, long double 特化版本的转换规则:

  • 安全转换:例如 complex<float>complex<double>,可以隐式进行
  • 不安全转换:例如 complex<long double>complex<double>,必须显式进行

拷贝的时候必须注意这种转换规则:

1
2
complex c1(c2);         
complex c1 = c2;

而赋值的事后允许接受不安全转换,这可能是 C++ 标准的失误:

1
2
complex c;
c = c1;

数值访问

1
2
3
4
5
6
7
8
9
real(c)
c.real()
c.real(1.7) 改实部
imag(c)
c.imag()
c.imag(1.7) 改虚部
abs(c) c 的绝对值
norm(c) c 的绝对值的平方
arg(c) c 的极坐标相角

比较

1
2
3
4
5
6
c1 == c2
c == 1.7
1.7 == c
c1 != c2
c != 1.7
1.7 != c

注意:

  1. 没有 <
  2. 如果没有自定义排序准则,不能在关联容器中以 complex<> 作为元素类型

算术

1
+ - * /

输入输出

1
2
ostrm << c
istrm >> c

输出操作符根据 stream 当前的状态和格式,将复数写出 (real, imag)

输入操作符接受以下任意一种格式,读取一个复数:

  • (real, imag)
  • (real)
  • real

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
pow(c, 3)
pow(c, 1.7)
pow(1.7, c)
pow(c1, c2)

exp(c)
sqrt(c)
log(c)
log10(c)

三角函数
反三角函数
双曲函数

$3 题目

复数 可以用字符串表示,遵循 “实部+虚部i” 的形式,并满足下述条件:

  • 实部 是一个整数,取值范围是 [-100, 100]
  • 虚部 也是一个整数,取值范围是 [-100, 100]
  • i^2 == -1

给你两个字符串表示的复数 num1 和 num2 ,请你遵循复数表示形式,返回表示它们乘积的字符串。

提示:

1
num1 和 num2 都是有效的复数表示。

示例 1:
输入:num1 = “1+1i”, num2 = “1+1i”
输出:”0+2i”
解释:(1 + i) (1 + i) = 1 + i2 + 2 i = 2i ,你需要将它转换为 0+2i 的形式。

示例 2:
输入:num1 = “1+-1i”, num2 = “1+-1i”
输出:”0+-2i”
解释:(1 - i) (1 - i) = 1 + i2 - 2 i = -2i ,你需要将它转换为 0+-2i 的形式。

代码 (C++)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
string complexNumberMultiply(string a, string b) {
int ra, ia;
get(a, ra, ia);
int rb, ib;
get(b, rb, ib);
complex<int> c1(ra, ia);
complex<int> c2(rb, ib);
complex<int> ans = c1 * c2;
string result = to_string(ans.real()) + '+' + to_string(ans.imag()) + 'i';
return result;
}

private:
void get(const string& a, int& ra, int& ia)
{
int n = a.size();
int i = 0;
while(i < n && a[i] != '+')
++i;
stringstream ss;
ss << a.substr(0, i);
ss >> ra;
++i;
ss.clear();
ss << a.substr(i);
ss >> ia;
}
};

Share