>>> from env_helper import info; info()
页面更新时间: 2023-06-24 12:30:31
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-9-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

3.1. SymPy-符号运算好帮手

SymPy是Python的数学符号计算库,用它可以进行数学公式的符号推导。为了调用方便,下面所有的 实例程序都假设事先从sympy库导入了所有内容:

>>> from sympy import *

3.1.1. 欧拉恒等式

数学中有一个著名的公式: eiπ + 1 = 0 ,叫做欧拉恒等式。 其中e是自然指数的底,i是虚数单位, π 是圆周率。 此公式被誉为数学最奇妙的公式,它将5个基本数学常数用加法、乘法和幂运算联系起来。 我曾经本以为用编程语言是没法表达这种公式的,现在看来果然是图样图森破。

下面用SymPy验证一下这个公式。 载入的符号中,E 表示自然指数的底, I 表示虚数单位, pi 表示圆周率, 因此上述的公式可以直接如下计算:

>>> from sympy import *
>>> E**(I*pi)+1
\[\displaystyle 0\]

欧拉恒等式可以下面的公式进行计算,

e^ix = cos(x) + i sin (x)

为了用SymPy求证上面的公式,我们需要引入变量 x 。 在SymPy中,数学符号是Symbol类的对象, 因此必须先创建之后才能使用:

>>> x = Symbol('x')

expand 函数可以将公式展开,我们用它来展开 `E**(I*pi)`` 试试看:

>>> expand( E**(I*x) )
\[\displaystyle e^{i x}\]

没有成功,只是换了一种写法而已。这里的 exp 不是 math.exp 或者 numpy.exp而是sympy.exp , 它是一个类,用来表述自然指数函数。 expand 函数有关键字参数 complex ,当它为 True 时,expand 将把公式分为实数和虚数两个部分:

>>> expand(exp(I*x), complex=True)
\[\displaystyle i e^{- \operatorname{im}{\left(x\right)}} \sin{\left(\operatorname{re}{\left(x\right)} \right)} + e^{- \operatorname{im}{\left(x\right)}} \cos{\left(\operatorname{re}{\left(x\right)} \right)}\]

这次得到的结果相当复杂,其中sin, cos, re, im都是sympy定义的类,re表示取实数部分, im表示取虚数部分。 显然这里的运算将符号x当作复数了。 为了指定符号x必须是实数,我们需要如下重新定义符号 x

>>> x = Symbol("x", real=True)
>>> expand(exp(I*x), complex=True)
\[\displaystyle i \sin{\left(x \right)} + \cos{\left(x \right)}\]

终于得到了我们需要的公式。那么如何证明它呢。我们可以用泰勒多项式展开:

>>> tmp = series(exp(I*x), x, 0, 10)
>>> pprint(tmp)
           2      3    4      5     6      7      8        9
          x    ⅈ⋅x    x    ⅈ⋅x     x    ⅈ⋅x      x      ⅈ⋅x      ⎛ 10⎞
1 + ⅈ⋅x - ── - ──── + ── + ──── - ─── - ──── + ───── + ────── + O⎝x  ⎠
          2     6     24   120    720   5040   40320   362880

series是泰勒展开函数,pprint将公式用更好看的格式打印出来。下面分别获得tmp的实部和虚部,分 别和cos(x)和sin(x)的展开公式进行比较:

>>> pprint(re(tmp))
   8      6    4    2
  x      x    x    x      ⎛ ⎛ 10⎞⎞
───── - ─── + ── - ── + re⎝O⎝x  ⎠⎠ + 1
40320   720   24   2
>>> pprint(series( cos(x), x, 0, 10) )
     2    4     6      8
    x    x     x      x      ⎛ 10⎞
1 - ── + ── - ─── + ───── + O⎝x  ⎠
    2    24   720   40320
>>> pprint(im(tmp))
   9       7      5    3
  x       x      x    x          ⎛ ⎛ 10⎞⎞
────── - ──── + ─── - ── + x + im⎝O⎝x  ⎠⎠
362880   5040   120   6
>>> pprint(series(sin(x), x, 0, 10))
     3     5     7       9
    x     x     x       x       ⎛ 10⎞
x - ── + ─── - ──── + ────── + O⎝x  ⎠
    6    120   5040   362880