超级懒人的工程:不动脑解方程

前言

在电子工程中,你有时需要使用标准公式来表征你的电路。你需要在多大程度上计算所有参数通常取决于要求。

例如,考虑一阶 RC 低通滤波器的 -3dB 截止频率公式:

$$f_c=\frac{1}{2\pi RC}$$

虽然此方程相当简单,大多数人可以在几秒钟内求解任何特定变量,但它可以作为如何符号求解方程的基本示例。

执行此任务最简单的方法之一是使用 SymPy,一个用于符号数学的 Python 库。

入门示例

首先,我们需要告诉 SymPy 公式是什么:

sympy_example.py
from sympy import *
f, R, C = symbols("f_c R C")
# 记住不要将其命名为 'f'(我们已经有名为 f 的符号!)
eq1 = Eq(f, 1 / (2 * pi * R * C))

通过使用 SymPy 版本的 $\pi$ 而不是 numpy 的版本,我们可以获得更高的数值精度,结果方程将以更易读的方式格式化,因为它们包含 $\pi$ 作为符号而不是

如果你收到类似这样的错误消息

sympy_install.txt
ImportError: No module named 'sympy'

你可以使用 pip 安装包(推荐,但 easy_install 也可以):pip install sympy

有关所用函数的详情,请参见优秀的 SymPy 教程

现在我们可以评估原始公式。由于这是一个方程并且我们想计算左边( $\frac{1}{2πRC}$ ),我们需要使用 .rhs 提取右边并用实际值替换变量(对于此示例,我们将使用 $1 k\Omega$ 和 $1 {\mu}F$)。最后但同样重要的是,我们使用 evalf() 函数将公式评估为单个浮点值

sympy_eval.py
f_result = eq1.rhs.evalf(subs={C: 1e-6, R: 1e3})

运行此代码块后,f_result 的值约为 159.155 — 这是正确的,可以使用以下方式轻松验证

下一步是让 SymPy 求解 R 的方程(在此示例中):

sympy_solve.py
from sympy.solvers import solve
eq1_R = solve(eq1, R)[0] # [0]:只取第一个解

注意对于更复杂的方程可能有多个解,你可能需要也可能不需要选择正确的解。在这种情况下只有一个解:print(eq1_R) 打印 1/(2*pi*C*f_c)

在 等前端中,SymPy 也能够使用各种美化打印方法。你可以使用以下命令初始化当前前端可用的最佳方法

sympy_print.py
from sympy import init_printing
init_printing()

IPython 中,公式将打印为 LaTeX,eq1_R 结果为

$$f_c = \frac{1}{2πCf_c}$$

在命令行上,将生成基于 ASCII 的输出:

sympy_ascii_output.txt
    1
─────────
2⋅π⋅C⋅f_c

现在我们可以简单地继续替换和评估新表达式。我们将使用前一个块的值来评估重新排列的公式 - 预期 R 的结果将正好是 1000$\Omega$。solve(...)[0] 已经返回方程的右边,所以我们不需要像上面那样使用 .rhs

sympy_eval_r.py
r_result = eq1_R.evalf(subs={C: 1e-6, f: f_result})

The value of r_result is exactly

$$1000.0\Omega$$

. For more complex equations, numerical errors might yield even if SymPy tries to avoid them as best as possible. You can often bypass small numerical errors being returned by using the chop=true argument to evalf(). A detailed explanation of the mechanisms involved would exceed the scope of this article, therefore it is recommended to read the SymPy reference on numerical evaluation.

懒化 SI 单位

你是否曾写过物理考试,通过将涉及的单位与预期输出单位匹配来推导正确的方程?无论如何,这不再必要。

SymPy 不仅可以懒化你对符号方程的处理,还集成了单位系统

例如,你可以计算上面列出的方程的单位:

sympy_units_example.py
from sympy.physics.units import *
print(1 / (ohms * farads))

这打印 $\frac{1}{s}$,考虑到上述方程产生 Hz 结果,这是正确的。

SymPy 不仅可以计算正确的推导单位,还能推导出称为 Hz 的单位

sympy_init_printing.py
print(find_unit(1 / (ohms * farads))) # ['Hz', 'hz', 'hertz', 'frequency']

我们也可以使用 SymPy 的单位知识从 中获取单位。我们将使用本文上一节列出的 eq1

目前,SymPy 不支持带单位的完整计算(参见此问题)。然而,当前的单位支持已经可以用于对方程进行合理性检查。将来我会尝试将 UliEngineering 的单位系统与 sympy 集成。


Check out similar posts by category: Python