当前位置: 首页
编程语言
SymPy自动因式分解:从面积拼图到代数恒等式

SymPy自动因式分解:从面积拼图到代数恒等式

热心网友 时间:2026-06-19
转载

利用SymPy自动因式分解并提取常数项,为形如(x+a)(x+b)的多项式生成矩形拼图的宽高和坐标,解决了Manim演示中不同公式需手动调整布局的痛点,实现了一类公式共用统一布局生成器。

今天专门解决一个非常具体的痛点——因式分解公式的可视化演示。

用SymPy自动因式分解:从面积拼图到代数恒等式

问题说穿了很简单:

你想用 Manimx2+5x+6=(x+2)(x+3)x2 + 5x + 6 = (x+2)(x+3) 通过“十字相乘”的面积模型展示出来。第一步你就得琢磨——这个大矩形怎么拆成四块?哪块是 x2x^22x2x3x3x6?它们的边长和位置又该怎么算?全得手动来。

好,这个问题搞定了。那么换个公式呢?改成 x2+7x+12x^2 + 7x + 12,布局又得从头算一遍。

这就引出最核心的问题了:有没有办法只告诉程序“我要做这个多项式的拼图证明”,它就能自动把尺寸和坐标全部算好?

答案是:有,用 SymPy

它能根据代数式的结构自动推导出几何布局,让你从“一个公式写一套代码”进化到“一类公式共用一套生成器”。

1. 痛点场景还原:公式一换,布局全乱

先来看一个典型的“手工布局”案例。

我们要把 x2+5x+6=(x+2)(x+3)x^2 + 5x + 6 = (x+2)(x+3) 的面积模型画出来,大矩形分成四块。代码大概长这样:

from manim import *class ManualX2Plus5xPlus6(Scene):
    def construct(self):
        x = 2  # 给 x 取个值来画图
        # 手动定义四块的宽高
        sq_x2 = Rectangle(width=x, height=x, color=BLUE, fill_opacity=0.4)
        rec_3x = Rectangle(width=3, height=x, color=RED, fill_opacity=0.4)
        rec_2x = Rectangle(width=x, height=2, color=RED, fill_opacity=0.4)
        rec_6 = Rectangle(width=3, height=2, color=GREEN, fill_opacity=0.4)
        # 手动拼装:左下角是 x^2,右边是 3x,上边是 2x,右上是 6
        sq_x2.shift(LEFT * (3 / 2) + DOWN * (2 / 2))
        rec_3x.next_to(sq_x2, RIGHT, buff=0)
        rec_2x.next_to(sq_x2, UP, buff=0)
        rec_6.next_to(rec_3x, UP, buff=0)
        self.play(Create(sq_x2), Create(rec_3x), Create(rec_2x), Create(rec_6))
        self.wait(1)

这段代码跑是能跑,但代价是每一处数字都是针对 x2+5x+6x^2 + 5x + 6 硬编码的。如果要改成 x2+7x+12=(x+3)(x+4)x^2 + 7x + 12 = (x+3)(x+4),那么:

  • 常数项从 2、3 变成 3、4;
  • rec_3x 的宽度要改成 4;
  • rec_2x 的高度要改成 3;
  • 小矩形 rec_6 的宽高要改成 4 和 3;
  • shift 里的偏移量也得跟着重新算。

每一次换公式都是一次手工劳动,而且还很容易出错。要是公式结构复杂一点,比如二次项系数不是 1,或者涉及到三项展开,这种手动模式基本就撑不住了。

2. SymPy 解决方案:因式分解 → 几何布局

SymPy 的真正厉害之处就在这里:它可以对多项式进行因式分解或展开,然后自动把每一项的系数和次数全都提取出来

而我们要做的,就是根据这些信息,自动生成对应的矩形拼图布局。

整个流程是这样的:

  1. 输入一个多项式字符串,比如 "x**2 + 5*x + 6"
  2. 让 SymPy 对它做因式分解,得到 (x + 2)*(x + 3)
  3. 从因式结果中读出两个一次式的常数项(2 和 3),从展开式中读出各项系数(1, 5, 6);
  4. 自动生成四个矩形块:x2x^2(边长 xx)、2x2x(宽 2 高 xx)、3x3x(宽 xx 高 3)、6(宽 2 高 3),然后根据这些边长自动算出它们左下角的坐标;
  5. 最后把布局信息打包成一个统一的数据结构,交给 Manim 去渲染。

这样做最大的好处是什么?不管输入是 x2+7x+12x^2 + 7x + 12x23x+2x^2 - 3x + 2,甚至是带参数的 x2+(a+b)x+abx^2 + (a+b)x + ab布局生成的逻辑完全一样——你只需要改一行输入字符串。

下面是一段纯 SymPy 的布局生成器代码,不依赖 Manim,可以直接在 Jupyter 里跑:

from sympy import symbols, factor, expand, Poly
from sympy.abc import xdef generate_layout(poly_expr):
    """
    输入:一个关于 x 的多项式(可因式分解为 (x+a)(x+b))
    输出:四个矩形的布局信息列表,每个矩形包括 (标签, 宽, 高, x坐标, y坐标)
    """
    # 因式分解
    factored = factor(poly_expr)            # 例如 (x + 2)*(x + 3)
    # 确保是两个一次因式
    if not factored.is_Mul:
        raise ValueError("多项式不能分解为两个一次因式")
    factors = factored.args
    if len(factors) != 2:
        raise ValueError("暂时只支持两个一次因式")
    # 提取常数项 a, b
    a = None
    b = None
    for fac in factors:
        if fac.is_Add:
            p = Poly(fac, x)
            if p.degree() == 1:
                const = p.coeff_monomial(1)  # 系数 1
                const_term = p.coeff_monomial(0)  # 常数项
                if const == 1:
                    val = const_term
                else:
                    val = const_term / const
            if a is None:
                a = val
            else:
                b = val
    # 展开式获取各项
    expanded = expand(poly_expr)
    poly = Poly(expanded, x)
    coeff_x2 = poly.coeff_monomial(2)  # x^2 系数
    coeff_x  = poly.coeff_monomial(1)  # x 系数
    const    = poly.coeff_monomial(0)  # 常数项
    # 返回布局,宽和高用数值表达式(含 x),留给 Manim 代入 x_val
    layout = [
        {"label": "x^2", "w": "x", "h": "x", "x0": 0, "y0": 0},
        {"label": f"{b}x", "w": b, "h": "x", "x0": "x", "y0": 0},
        {"label": f"{a}x", "w": "x", "h": a, "x0": 0, "y0": "x"},
        {"label": f"{a*b}", "w": b, "h": a, "x0": "x", "y0": "x"},
    ]
    return layout, a, b# 示例:x^2 + 5x + 6
layout, a, b = generate_layout(x**2 + 5*x + 6)
print("a =", a, " b =", b)
for item in layout:
    print(item)

输出结果如下:

a = 2  b = 3
{'label': 'x^2', 'w': 'x', 'h': 'x', 'x0': 0, 'y0': 0}
{'label': '3x', 'w': 3, 'h': 'x', 'x0': 'x', 'y0': 0}
{'label': '2x', 'w': 'x', 'h': 2, 'x0': 0, 'y0': 'x'}
{'label': '6', 'w': 3, 'h': 2, 'x0': 'x', 'y0': 'x'}

可以看到,矩形的宽高和坐标全部由 ab 决定,而 a,b 是从 SymPy 的因式分解结果中自动提取的。换个多项式,只需要改一行输入,布局自动就能生成。

3. Manim 联动实战:通用因式分解拼图动画

现在我们把这个自动布局引擎接入 Manim,做一个通用场景:只需要在开头指定一个多项式,动画就会自动展示对应的面积拼图,并标注出公式。

完整代码如下:

from manim import *
from sympy import factor, Poly
from sympy.abc import xclass AutoFactorPuzzle(Scene):
    def construct(self):
        # ========== 1. 在这里输入你要讲的多项式 ==========
        poly_expr = x**2 + 5 * x + 6  # 试着改成 x**2 + 7*x + 12 看看!
        x_val = 1.5  # 动画中 x 的具体取值(可调)
        # ========== 2. SymPy 自动分析多项式 ==========
        factored = factor(poly_expr)
        if not factored.is_Mul or len(factored.args) != 2:
            raise ValueError("多项式需能分解为两个一次因式 (x+a)(x+b)")
        # 提取 a, b
        roots = []
        for fac in factored.args:
            p = Poly(fac, x)
            if p.degree() != 1:
                raise ValueError("因式必须是一次式")
            coeffs = p.all_coeffs()
            root = -coeffs[1] / coeffs[0]
            roots.append(root)
        a, b = float(roots[0]), float(roots[1])  # 常数项 a, b
        # ========== 3. 根据 a, b 生成矩形布局 ==========
        blocks = [
            {"label": "x^2", "w": x_val, "h": x_val, "x0": 0, "y0": 0, "color": BLUE},
            {
                "label": f"{abs(b)} \times x",
                "w": abs(b),
                "h": x_val,
                "x0": x_val,
                "y0": 0,
                "color": RED,
            },
            {
                "label": f"{abs(a)} \times x",
                "w": x_val,
                "h": abs(a),
                "x0": 0,
                "y0": x_val,
                "color": YELLOW,
            },
            {
                "label": f"{abs(b)} \times {abs(a)}",
                "w": abs(b),
                "h": abs(a),
                "x0": x_val,
                "y0": x_val,
                "color": GREEN,
            },
        ]
        # ========== 4. Manim 绘制 ==========
        for blk in blocks:
            rect = Rectangle(
                width=blk["w"],
                height=blk["h"],
                color=blk["color"],
                fill_opacity=0.4,
                stroke_width=1,
            )
            rect.move_to([blk["x0"] + blk["w"] / 2, blk["y0"] + blk["h"] / 2, 0])
            rect.shift(LEFT * 2 + DOWN)
            label = MathTex(f"{blk['label']}", font_size=16)
            label.move_to(rect.get_center())
            self.play(Create(rect), Write(label))
        self.wait(0.5)
        # 显示等式
        eq = MathTex(
            f"{{x}}^2 + {poly_expr.coeff(x,1)}x + {poly_expr.coeff(x,0)}",
            "=",
            f"(x{a if a<0 else abs(a)})(x{b if b<0 else abs(b)})",
            font_size=20,
        ).shift(DOWN * 1.5)
        self.play(Write(eq))
        self.wait(2)

关键点需要说明一下

  • 多项式的输入只改 poly_expr = ... 这一行,一整段代码就能自动绘制出对应的十字相乘面积图;
  • SymPy 的 factor 自动拆出一次因式,Poly 帮我们提取出系数,ab 直接成为矩形的边长参数;
  • 整个布局的坐标逻辑只写了一次,通过 abx_val 计算出 blocks,完全没有手动偏移的操作。

试试把 poly_expr 改成 x**2 + 7*x + 12,重新运行一次。动画会立刻切换成 x2x^2(蓝)、4x4x(红)、3x3x(黄)、1212(绿)的四块拼图,等式也会同步更新为 x2+7x+12=(x+4)(x+3)x^2+7x+12=(x+4)(x+3)

4. 效果展示说明

运行上面这个 AutoFactorPuzzle,你会看到:

  1. 四块矩形依次浮现:蓝色 x2x^2 在左下角,右侧是一块红色的 bxbx,上方是一块黄色的 axax,右上角是绿色的常数块 abab。所有块之间严丝合缝,因为它们的坐标和边长都来自同一个因式分解结果。
  2. 标签 x2x^2bxbxaxaxabab 精准地位于每块的中心,清晰对应着代数项。
  3. 画面下方会显示因式分解的等式——左边是展开式,右边是因式乘积。学生可以立刻把图形和公式对应起来。

更关键的是:换一个多项式只需要改一行代码,动画逻辑完全复用。

如果想一次性展示多个公式的对比,只需要建几个不同的场景实例即可。

这意味着,制作一套完整的“因式分解几何证明”微课,可以从一天的工作量缩短到一小时。

5. 小结

SymPy 在这个场景里扮演的角色,本质上是一个代数结构的自动解析器

传统方法当然也能拼出图,但你需要用大脑去“解析”公式,再手动翻译成矩形的宽高和位置;

SymPy 帮你自动完成了“因式分解 → 提取系数 → 生成几何参数”的全过程,让你可以专注于教学设计本身和动画的视觉效果美化。

这个模式可以轻松扩展到:

  • 二次三项式的十字相乘面积模型(就是本文的例子);
  • 完全平方和平方差公式的拼图证明;
  • 多项式乘法的面积表示,比如 (x+a)(x+b)(x+c)(x+a)(x+b)(x+c) 的体积模型;
  • 甚至更复杂的恒等式,只要你能把代数结构映射为空间的分割。
来源:https://juejin.cn/post/7650451521307852843

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
用 LlamaIndex 做 RAG 前,先把 Reader、Index、Retriever 的边界写清楚

用 LlamaIndex 做 RAG 前,先把 Reader、Index、Retriever 的边界写清楚

LlamaIndex 不适合用“5 行代码做一个 RAG demo”来判断好坏。那个 demo 只能证明框架能跑通一次,不证明你的数据进入系统后仍然可追踪,不证明检索结果能解释,不证明 Agent 的

时间:2026-07-13 14:05
Go语言AES混淆加密解密敏感数据详解

Go语言AES混淆加密解密敏感数据详解

Go语言AES加密需注意:密钥长度必须为16、24或32字节,否则会引发panic;CBC模式解密乱码常因IV或PKCS7填充错误;GCM模式中nonce不可重用,否则密钥可被恢复;ECB模式因明文块输出固定密文,存在安全风险,不建议使用。

时间:2026-07-13 06:53
C++ std::atomic::wait高性能轮询等待原子变量状态变化

C++ std::atomic::wait高性能轮询等待原子变量状态变化

C++20的std::atomic::wait是轻量级等待机制,需GCC11+ Clang12+及glibc≥2 34,macOS不支持。需与notify配对,注意内存序,循环检查防虚假唤醒。超时版本精度有限,高性能关键在notify时机与内存序正确性。

时间:2026-07-13 06:53
VSCode左侧边栏不见了?快速找回方法

VSCode左侧边栏不见了?快速找回方法

按Ctrl+B或Cmd+B可恢复被误触隐藏的侧边栏。若无效,需检查窗口焦点是否在编辑器、是否处于全屏或Zen模式、workbench activityBar visible配置项、扩展冲突以及远程环境同步问题,并逐一排查。

时间:2026-07-13 06:53
VSCode中利用Node批量修改多媒体文件元数据标签

VSCode中利用Node批量修改多媒体文件元数据标签

music-metadata库支持跨格式读写MP3、FLAC、M4A、WAV等音频元数据,需先用parseFile()初始化,再调用writeMetadata()写入。批量修改前必须验证写入支持,封面图片需为Uint8Array格式。在VSCode终端运行脚本比插件更可控,处理中文路径时需切换终端代码页为UTF-8并指定ID3v2 3版本以避免乱码。

时间:2026-07-13 06:53
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜