楔子
本篇文章来聊一聊复数,尽管在日常开发中基本用不到复数,但对它有一个深刻的认识,知道它是做什么的,个人觉得还是很有必要的。另外,本专栏力求精致、详细,因此每一个细节都要到位。
那么下面就来解释一下什么是复数。
什么是复数
复数是一种扩展实数的数,它由实数和虚数两部分组成,用来解决实数范围内无法解决的问题,基本形式如下。
形如 a + bi 的数,我们称之为复数,其中 a 和 b 是浮点数(实数),i 是虚数,满足 i 的平方等于 -1。
所以复数不仅包含实数,还包含虚数,形式为 a + bi,然后 a 被称为复数的实部,b 被称为复数的虚部。如果两个复数的实部相同,虚部相反,那么它们互为共轭复数,比如 1 + 3i 和 1 - 3i。
如果对复数的实部和虚部进行平方和再开根号,便可得到复数的模,比如 3 + 4i 的模便是 5。
复数的引入可以帮助我们更好地理解和解决许多数学以及物理问题,特别是在涉及振动、波动和电路分析等领域,比如:
电工程:分析交流电路和信号处理;
控制系统:用于系统稳定性分析;
量子力学:描述波函数和量子态;
流体力学:用于描述流动问题;
当然复数也有自己的运算规则。
加法:两个复数相加是对应的实部和虚部相加
减法:两个复数相减是对应的实部和虚部相减。
乘法:两个复数的乘法使用分配律
除法:两个复数的除法涉及到共轭复数
以上就是复数的基本概念,下面来看看 Python 的复数是怎么实现的。
复数的底层结构
复数的实现比想象中的简单很多,说白了就是维护两个浮点数而已。
// Include/cpython/complexobject.h
typedef struct {
double real;
double imag;
} Py_complex;
typedef struct {
PyObject_HEAD
Py_complex cval;
} PyComplexObject;
我们看到复数的结构和浮点数是非常相似的,只不过浮点数只用一个 double 来维护具体的值。而复数因为存在实部和虚部,因此需要两个 double,其中 real 维护复数的实部,imag 维护复数的虚部。
# 在别的语言中,虚数都是用 i 来表示
# 而 Python 觉得 i 是一个很常用的变量,所以使用 j 来表示虚数
cpx = 3 + 4j
# 其中 3 为实部,4 为虚部
print(cpx) # (3+4j)
# 如果虚部为 1,那么要写成 1j,不能只写 j
# 否则解释器会认为 j 是一个变量
print(3 + 1j) # (3+1j)
# 复数的实部可以为 0
print(2j) # 2j
# 当然虚部也可以为 0,如果虚部为 0,那么要写成 0j,不能不写
# 因为 3 和 3 + 0j 不是等价的,前者是整数,后者是复数
print(0j) # 0j
print(3 + 0j) # (3+0j)
整个过程非常简单,当解释器看到 3 + 4j 的时候,就知道要创建复数了,因为解释器对内置的数据结构了如指掌,所以在底层会创建一个 PyComplexObject 结构体实例。