码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 告别手动计算,SymPy 初识与 Manim 联动


    合集 - manim动画(43)
    1.【manim动画教程】-- 安装2023-03-282.【manim动画教程】-- 基本图形2023-03-293.【manim动画教程】-- 坐标系2023-04-104.【manim动画教程】-- 文本样式2023-04-075.【manim动画教程】-- 文字和公式2023-04-046.【manim动画教程】-- 图形样式2023-03-317.【manim动画教程】--相机2023-04-198.【manim动画教程】--高级动画效果2023-04-149.【manim动画教程】--常用动画效果2023-04-1210.【manim】之滚动字幕2022-12-0611.【manim】之圆规动画2023-01-3112.【manim】之目录动画2023-02-2813.Manim:动画制作背后的魔法2025-05-1814.manim 动画效果总结2025-05-2015.manim变换效果总结2025-05-2116.Manim动画渲染:从代码到屏幕的幕后故事2025-05-2217.轻松掌握Manim的.animate语法:让动画编程更简单2025-05-2518.Manim中三种函数图像类的比较2025-06-0519.掌握ChangeSpeed类:让数学动画速度随心而动!2025-06-1520.把数学对象画出来:Manim Mobject类库速查手册2025-08-1621.「亲手画出动态数学」:让数学可视化触手可及的Manim入门课2025-11-0722.让你的动画“活”过来:Manim 节奏控制指南 (Rate Functions)2025-11-2323.Manim进阶:用背景图片让你的数学视频脱颖而出2025-11-2624.Manim v0.19.1 发布啦!三大新特性让动画制作更丝滑2025-12-0225.🚀 Manim CE v0.20.0 发布:动画构建更丝滑,随机性终于“可控”了!02-2126.ManimCE v0.20.1 发布:LaTeX 渲染修复与动画稳定性提升03-0227.探索视觉的边界:用 Manim 重现有趣的知觉错觉03-0728.用Manim实现动态交点计算--从一个动点问题说起04-1629.Manim如何在数学公式中完美显示中文?04-1930.如何灵活设置公式中各个部分的颜色?04-2231.如何让多个动画“齐步走”?04-26
    32.告别手动计算,SymPy 初识与 Manim 联动05-16
    33.让数学公式自动推导05-1734.切线的魔法:用 SymPy 和 Manim 轻松搞定导数动画05-1935.填充与积累:积分与面积的可视化05-2136.轨迹的蓝图:方程求解与交点计算05-2337.Manim物理模拟:别自己写欧拉了!05-2538.用 SymPy 解决 Manim 曲线绘制速度不均的问题06-0139.一次函数图像工厂:用 SymPy 自动生成 y=kx+b 对比动画06-0340.用SymPy自动计算抛物线求根、判别式与顶点06-0541.用SymPy自动求解三角形构造与全等条件验证06-0842.用SymPy自动求解追及问题的方程06-1043.用SymPy自动因式分解:从面积拼图到代数恒等式06-13
    收起

    下面是我正在做的一个抛物线演示动画。

    需求很简单:展示一个二次函数 $ y = x^2 - 2x - 1 $ 的图像,并在上面标注几个关键点。

    问题来了:

    • 当我想调整函数参数时(比如把 $ -2x $ 改成 $ -3x $),所有点的坐标都要手动重算
    • 计算 $ x=1.5 $ 时的函数值?掏出计算器 → $ 1.5^2 - 2×1.5 - 1 = -1.75 $ → 再手动填回代码
    • 顶点坐标?求导 → 令导数等于0 → 解方程 → 计算 y 值 → 再填回代码
    • 对称轴和 x 轴的交点?求根公式 → 计算器 → 填代码

    一个参数改动,我要重新计算七八个坐标值。这哪是在做动画,分明是在做数学作业!

    直到我发现了 SymPy 这个神器。

    SymPy 是什么?为什么 Manim 动画需要它?

    简单说,SymPy 是一个 Python 的符号计算库。

    别被"符号计算"这个词吓到,用大白话讲就是:

    让计算机帮你"列式子、解方程、求导数",而不是你自己手算。

    数值计算 vs 符号计算

    看一个更直观的对比,你会立刻明白符号计算的强大:

    import math
    import sympy as sp
    
    # ========== 场景:计算 sin(π/3) 的精确值 ==========
    # 数值计算 - 得到近似小数
    result_num = math.sin(math.pi / 3)
    print(f"数值计算: {result_num}")  
    # 输出: 0.8660254037844386  ← 这是近似值,不知道它等于 √3/2
    
    # 符号计算 - 得到精确表达式
    x = sp.Symbol('x')
    result_sym = sp.sin(sp.pi / 3)
    print(f"符号计算: {result_sym}")  
    # 输出: sqrt(3)/2  ← 精确的数学表达式!
    
    
    # 场景1:求平方
    print("\n=== 求 (sin(π/3))² ===")
    # 数值计算 - 精度损失
    square_num = result_num ** 2
    print(f"数值: {square_num}")  
    # 输出: 0.7499999999999999  ← 本应是 0.75,有浮点误差!
    
    # 符号计算 - 精确化简
    square_sym = result_sym ** 2
    print(f"符号: {square_sym}")  
    # 输出: 3/4  ← 精确值!
    

    关键对比总结

    特性 数值计算 (math) 符号计算 (sympy)
    sin(π/3) 0.86602540378... √3/2
    平方后 0.749999999999... 3/4
    能否继续代数运算 ❌ 只能数值近似 ✅ 可代入方程、求导、化简
    浮点精度问题 ⚠️ 存在误差累积 ✅ 完全精确

    符号计算的灵活性体现在:

    1. 保持数学形式:√3/2 比 0.866... 更有数学意义
    2. 自动化简:(√3/2)² 自动变成 3/4
    3. 代数兼容:可以继续解方程、求导、积分,保持精确形式

    这对 Manim 动画尤为重要——你不仅需要坐标值,更需要数学关系的可视化,而符号计算保留了这种关系!

    避免累积误差

    符号计算在累积的计算中,能够有效的降低误差。

    比如公式:$ I_n =1-n\times I_{n-1} $其中 $ I_0 = e-1 $。分别累积计算以后:

    $ n $ 符号计算 数值计算 (模拟8位小数精度) 误差分析
    0 $ e - 1 $ 0.71828183 初始误差: $ \approx 1.5 \times 10^{-9} $
    1 $ 2 - e $ 0.28171817 误差微小
    2 $ 2e - 5 $ 0.43656366 误差开始累积
    3 $ 16 - 6e $ 0.30860902
    4 $ 24e - 65 $ 0.23687292
    5 $ 326 - 120e $ 0.18276460 误差开始显现
    6 $ 1956e - 5315 $ 0.15054840
    7 $ 13692 - 5040e $ 0.12145720
    8 $ 109536e - 298325 $ 0.10364240
    9 $ 985824 - 2691360e $ 0.08385840
    10 $ 26913600e - 73309365 $ 0.07515840 偏差明显
    11 $ 296049600 - 807408000e $ 0.09173440
    12 $ 9688896000e - 26384952005 $ -0.08345440 灾难性错误:符号反转!
    13 $ 342938611200 - 1258293216000e $ 2.10490720 完全失控

    使用Sympy的话,可以在需要某一步结果的时候再代入$ e $去具体计算出来,不会累积误差。

    SymPy 核心入门:把变量当作"符号"

    在 SymPy 中,我们首先要定义符号变量:

    import sympy as sp
    
    # 定义符号 - 告诉 SymPy "x 是一个数学变量,不是具体的数"
    x = sp.Symbol('x')
    y = sp.Symbol('y')
    
    # 现在可以构建表达式了
    expr = x**2 - 2*x - 1  # y = x² - 2x - 1
    print(expr)  # 输出: x**2 - 2*x - 1
    

    核心操作:代入求值 .subs()

    有了表达式,我们可以轻松计算任意 x 对应的 y 值:

    # 计算 x=1.5 时的函数值
    result = expr.subs(x, 1.5)
    print(result)  # 输出: -1.75000000000000
    print(float(result))  # 转换为浮点数: -1.75
    

    自动求导和解方程

    这才是真正解放双手的功能:

    # 求导数
    derivative = sp.diff(expr, x)  # 对 x 求导
    print(derivative)  # 输出: 2*x - 2
    
    # 解方程:导数=0(找顶点)
    vertex_x = sp.solve(derivative, x)[0]  # 解得 x=1
    vertex_y = expr.subs(x, vertex_x)      # 代入求 y
    print(f"顶点坐标: ({vertex_x}, {vertex_y})")  # 输出: (1, -2)
    
    # 解方程:y=0(找与x轴交点)
    roots = sp.solve(expr, x)
    print(f"与x轴交点: {roots}")  # 输出: [1 - sqrt(2), 1 + sqrt(2)]
    

    看到了吗? 原本需要手动计算的所有值,现在 SymPy 全自动搞定了!

    SymPy 和 Manim 结合示例

    现在我们把 SymPy 和 Manim 结合起来,做一个参数可调的抛物线动画。

    核心代码示例

    from manim import *
    import sympy as sp
    
    class AutoParabola(Scene):
        def construct(self):
            # ========== SymPy 自动计算部分 ==========
            x = sp.Symbol('x')
            a, b, c = 1, -2, -1                      # 抛物线参数:y = ax² + bx + c
            expr = a * x**2 + b * x + c              # SymPy 符号表达式
    
            # 自动求顶点:令导数为 0
            derivative = sp.diff(expr, x)            # 求导:2ax + b
            vertex_x = float(sp.solve(derivative, x)[0])
            vertex_y = float(expr.subs(x, vertex_x))
    
            # 自动求与 x 轴交点
            roots = sp.solve(expr, x)                # 解方程 ax² + bx + c = 0
            root_points = [(float(r), 0) for r in roots if r.is_real]
            
            # ========== Manim 可视化部分 ==========
            axes = Axes(x_range=[-2, 4, 1], y_range=[-3, 3, 1], axis_config={"color": BLUE})
            
            # 用 SymPy 表达式直接作为绘图函数
            parabola = axes.plot(
                lambda x_val: float(expr.subs(x, x_val)),  # SymPy 实时计算 y 值
                color=YELLOW, stroke_width=3,
            )
            
            # 顶点(使用 SymPy 算出的坐标)
            vertex_dot = Dot(axes.c2p(vertex_x, vertex_y), color=RED)
            vertex_label = MathTex(
                f"({vertex_x:.1f}, {vertex_y:.1f})", font_size=24, color=RED
            ).next_to(vertex_dot, UP)
    
            # x 轴交点
            root_dots = VGroup(*[
                Dot(axes.c2p(rx, ry), color=GREEN) for rx, ry in root_points
            ])
    
            # ========== 动画播放 ==========
            self.play(Create(axes))
            self.play(Create(parabola))
            self.play(Create(vertex_dot), Write(vertex_label))
            self.play(Create(root_dots))
            self.wait(2)
    

    代码核心解析

    关键点1:无缝衔接

    # SymPy 计算出的值是符号类型,需要转为 float 给 Manim 使用
    vertex_x = float(sp.solve(derivative, x)[0])
    

    关键点2:动态函数映射

    # 用 lambda 将 SymPy 表达式"翻译"成 Manim 能理解的数值函数
    parabola = axes.plot(
        lambda x_val: float(expr.subs(x, x_val)),
        color=YELLOW,
    )
    

    关键点3:坐标系转换

    # 数学坐标 → 屏幕坐标
    vertex_dot = Dot(axes.c2p(vertex_x, vertex_y))
    

    效果展示说明

    运行这段代码后,你会看到:

    1. 坐标轴自动建立,范围根据函数特点自适应
    2. 抛物线精确绘制,形状由 SymPy 实时计算
    3. 红色顶点自动标注在正确位置,坐标值精确显示
    4. 绿色交点标记出抛物线与 x 轴的交点
    5. 白色虚线标出对称轴位置

    最神奇的是:如果你想改成 $ y = 2x^2 + 3x - 1 $,只需要修改第 11 行的参数:

    a, b, c = 2, 3, -1  # 其他代码完全不用动!
    

    所有的点、线、标注都会自动更新到正确位置!修改后:

    小结

    今天我们解决了 Manim 动画制作中的一大痛点:手动计算坐标。

    通过 SymPy 的符号计算能力,我们实现了:

    • ✅ 表达式精确计算:告别计算器
    • ✅ 适合数学思维表达:将公式推导直接映射成代码
    • ✅ 自动求导找顶点:告别手算求导
    • ✅ 自动解方程找交点:告别求根公式
    • ✅ 等等... ...

    核心代码模板:

    import sympy as sp
    x = sp.Symbol('x')
    expr = x**2 - 2*x - 1  # 你的表达式
    y_value = float(expr.subs(x, x_value))  # 计算任意点的值
    
  • 相关阅读:
    自定义开发odoo14的统计在线用户人数
    Packet Tracer - 配置 IPv6 的 EIGRP 基本设置
    易排通用规划平台,以Excel作为数据源的调用方法与数据文件说明
    rknn_toolkit以及rknpu环境搭建-rv1126
    软件需求—《软件工程与计算》笔记
    python 图片下面加边框TK界面
    独立产品灵感周刊 DecoHack #026 - 在哪里推广你的新产品
    Java线程学习入门(二)
    基于51单片机温度监控Proteus仿真设计_报警值可调
    中国剩余定理(crt)和扩展中国剩余定理(excrt)
  • 原文地址:https://www.cnblogs.com/wang_yb/p/20058938
  • 最新文章
  • 沪漂五周年了:我越来越迷茫了
    Agentic Skill Routing 实战:别再把所有 Skill 塞进 AI Agent 上下文
    MySQL-Seconds_behind_master的精度误差
    [MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间
    AI的至暗历史:从万众期待到被政府撤资,AI的两次死亡徘徊
    Agent OS :五种驯服不确定性的范式
    PortSwigger SQL注入LAB11
    数据库即时编译JIT
    [Begin]AI Learn Data Day 0
    深度学习进阶(二十七)现代 LLM 的核心架构设计其二:SwiGLU
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号