alternating_series.py
1# -*- coding: utf-8 -*-2from manim import *3import numpy as np4 5class AlternatingSeriesConvergence(Scene):6 def construct(self):7 # 设置默认字体8 Text.set_default(font="SimSun")9 10 # 标题11 title = Text("交错级数收敛性").scale(0.8)12 title.to_edge(UP, buff=0.5)13 self.play(Write(title))14 self.wait(1)15 16 # 创建交错级数的各项17 terms = VGroup()18 n_visible_terms = 6 # 减回到6项19 for i in range(n_visible_terms):20 if i == 0:21 term = MathTex("1")22 else:23 sign = "-" if i % 2 == 1 else "+"24 term = MathTex(f"{sign}\\frac{{1}}{{{i+1}}}")25 terms.add(term)26 terms.add(MathTex("\\cdots"))27 terms.arrange(RIGHT, buff=0.2)28 29 # 创建完整的级数表达式30 series = VGroup(31 MathTex("\\sum_{n=1}^{\\infty} (-1)^{n+1}\\frac{1}{n} ="),32 terms33 ).arrange(RIGHT, buff=0.3).scale(0.8)34 series.move_to(ORIGIN + UP * 2) # 居中显示在上方35 36 # 添加收敛性说明(移到右上方)37 explanation = VGroup(38 Text("• 通项绝对值单调递减", font="SimSun"),39 Text("• 通项趋于零", font="SimSun"),40 Text("• 级数收敛于ln(2)", font="SimSun")41 ).arrange(DOWN, aligned_edge=LEFT).scale(0.5)42 explanation.to_corner(UR, buff=0.5) # 移到右上角43 44 # 添加误差估计(跟随说明文字)45 error_bound = MathTex(46 r"|R_n| \leq \frac{1}{n+1}",47 color=BLUE48 ).scale(0.7)49 error_bound.next_to(explanation, DOWN, buff=0.5)50 51 error_text = Text(52 "误差界估计",53 font="SimSun"54 ).scale(0.5).next_to(error_bound, UP, buff=0.2)55 56 self.play(Write(series))57 self.wait(1)58 59 # 创建坐标系(居中显示)60 axes = Axes(61 x_range=[0, 20, 2],62 y_range=[-0.5, 1.5, 0.5],63 axis_config={64 "include_tip": True,65 "include_numbers": False66 },67 x_length=10, # 增加宽度68 y_length=6 # 增加高度69 ).move_to(ORIGIN + DOWN * 0.5) # 居中显示,稍微下移70 71 # 添加分数刻度标签72 y_labels = VGroup()73 y_values = [-0.5, 0, 0.5, 1, 1.5]74 for y in y_values:75 if y == 0:76 label = MathTex("0")77 elif y == 1:78 label = MathTex("1")79 else:80 num, den = float(y).as_integer_ratio()81 label = MathTex(f"\\frac{{{num}}}{{{den}}}")82 label.scale(0.5)83 label.next_to(axes.c2p(0, y), LEFT, buff=0.1)84 y_labels.add(label)85 86 # 添加x轴刻度标签(使用整数)87 x_labels = VGroup()88 for x in range(0, 21, 2):89 if x > 0: # 跳过原点90 label = MathTex(f"{x}").scale(0.5)91 label.next_to(axes.c2p(x, 0), DOWN, buff=0.1)92 x_labels.add(label)93 94 # 添加坐标轴标签95 x_label = Text("n", font="SimSun").scale(0.6).next_to(axes.x_axis, RIGHT)96 y_label = Text("部分和", font="SimSun").scale(0.6).next_to(axes.y_axis, UP)97 98 self.play(99 Create(axes),100 Write(x_label),101 Write(y_label),102 Write(x_labels),103 Write(y_labels)104 )105 106 # 计算部分和107 def get_partial_sum(n):108 return sum((-1)**(k+1)/k for k in range(1, n+1))109 110 # 创建高亮框111 highlight_box = SurroundingRectangle(terms[0], color=YELLOW)112 self.play(Create(highlight_box))113 114 # 创建部分和点和折线115 dots = VGroup()116 n_terms = 20117 partial_sums = [get_partial_sum(n) for n in range(1, n_terms+1)]118 119 # 创建点120 prev_dot = None121 for i, sum_value in enumerate(partial_sums):122 dot = Dot(axes.c2p(i+1, sum_value), color=RED)123 dots.add(dot)124 125 if prev_dot:126 line = Line(prev_dot.get_center(), dot.get_center(), color=YELLOW)127 self.play(128 Create(dot),129 Create(line),130 run_time=0.3131 )132 else:133 self.play(Create(dot), run_time=0.3)134 prev_dot = dot135 136 # 更新高亮框位置137 if i < len(terms) - 1:138 new_box = SurroundingRectangle(terms[:i+1], color=YELLOW)139 self.play(140 Transform(highlight_box, new_box),141 run_time=0.3142 )143 144 # 显示极限值145 limit_value = np.log(2)146 limit_line = DashedLine(147 axes.c2p(0, limit_value),148 axes.c2p(20, limit_value),149 color=GREEN150 )151 limit_label = MathTex(r"\ln(2)", color=GREEN).scale(0.8)152 limit_label.next_to(limit_line.get_end(), RIGHT)153 154 self.play(155 Create(limit_line),156 Write(limit_label)157 )158 159 # 添加收敛性说明160 explanation = VGroup(161 Text("• 通项绝对值单调递减", font="SimSun"),162 Text("• 通项趋于零", font="SimSun"),163 Text("• 级数收敛于ln(2)", font="SimSun")164 ).arrange(DOWN, aligned_edge=LEFT).scale(0.5)165 explanation.to_corner(UR, buff=0.5) # 移到右上角166 167 self.play(Write(explanation))168 169 # 显示振荡收敛的特点170 oscillation = Text(171 "交错级数的部分和在极限值附近振荡收敛",172 font="SimSun"173 ).scale(0.5)174 oscillation.to_edge(DOWN, buff=0.5)175 176 self.play(Write(oscillation))177 self.wait(2)178 179 # 添加误差估计180 error_bound = MathTex(181 r"|R_n| \leq \frac{1}{n+1}",182 color=BLUE183 ).scale(0.7)184 error_bound.next_to(explanation, DOWN, buff=0.5)185 186 error_text = Text(187 "误差界估计",188 font="SimSun"189 ).scale(0.5).next_to(error_bound, UP, buff=0.2)190 191 self.play(192 Write(error_text),193 Write(error_bound)194 )195 self.wait(2) 讲解
这个视频围绕「交错级数收敛性」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「交错级数收敛性」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
核心公式可以写成:
这类公式可以和画面中的符号一一对应。
观察路径
观察路径可以分三步:先锁定「交错级数收敛性」中的核心对象,尤其留意交错级数、级数收敛、误差估计之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从交错级数、级数收敛、误差估计这些概念进入,继续沿相邻问题观察同一类数学结构。