阶段 03 讲义
数学 11h:高数 · 导数与微分(一)
编程 9h:循环(for / while)
第一部分 · 数学
1 导数的定义 ⭐
从实际问题来:一辆车走了 $s(t)$ 米,问它在时刻 $t_0$ 的瞬时速度是多少?
平均速度好算:$\frac{\Delta s}{\Delta t} = \frac{s(t_0+\Delta t) - s(t_0)}{\Delta t}$
但"瞬时"意味着 $\Delta t \to 0$。于是:
$$v(t_0) = \lim_{\Delta t \to 0}\frac{s(t_0+\Delta t) - s(t_0)}{\Delta t}$$
这就是导数。
1.1 定义
$$f'(x_0) = \lim_{\Delta x \to 0}\frac{f(x_0+\Delta x) - f(x_0)}{\Delta x}$$
也常写成:
$$f'(x_0) = \lim_{x \to x_0}\frac{f(x) - f(x_0)}{x - x_0}$$
其他记号:$y'$、$\frac{dy}{dx}$、$\frac{df}{dx}$
1.2 几何意义 ★
$$\frac{f(x_0+\Delta x) - f(x_0)}{\Delta x}$$
是割线的斜率。当 $\Delta x \to 0$,割线趋向切线。
所以:导数的几何意义 = 曲线在该点切线的斜率。
这带来两个直观:
- $f'(x_0) > 0$ → 曲线在上升
- $f'(x_0) < 0$ → 曲线在下降
- $f'(x_0) = 0$ → 切线水平(可能是极值点)
1.3 物理意义
导数是变化率:
- 位置 → 速度 → 加速度(速度的导数)
- 任何"某量的变化快慢"都是导数
1.4 用定义求导:完整例子
求 $f(x) = x^2$ 的导数
第一步:写出差商
$$\frac{f(x+\Delta x) - f(x)}{\Delta x} = \frac{(x+\Delta x)^2 - x^2}{\Delta x}$$
第二步:展开分子
$$= \frac{x^2 + 2x\Delta x + (\Delta x)^2 - x^2}{\Delta x} = \frac{2x\Delta x + (\Delta x)^2}{\Delta x}$$
第三步:约掉 $\Delta x$(注意 $\Delta x \ne 0$)
$$= 2x + \Delta x$$
第四步:取极限 $\Delta x \to 0$
$$f'(x) = 2x$$
∎
套路:展开 → 约去 $\Delta x$ → 取极限。
关键在第 2 步到第 3 步:必须先把 $\Delta x$ 约掉,否则取极限会出现 0/0。
1.5 再练一个:$\sqrt{x}$
$$\frac{\sqrt{x+\Delta x} - \sqrt{x}}{\Delta x}$$
分子有理化(乘共轭):
$$= \frac{(\sqrt{x+\Delta x} - \sqrt{x})(\sqrt{x+\Delta x} + \sqrt{x})}{\Delta x(\sqrt{x+\Delta x} + \sqrt{x})} = \frac{\Delta x}{\Delta x(\sqrt{x+\Delta x}+\sqrt{x})}$$
$$= \frac{1}{\sqrt{x+\Delta x}+\sqrt{x}} \xrightarrow{\Delta x\to0} \frac{1}{2\sqrt{x}}$$
技巧:遇到根号,有理化是标准操作。
2 基本求导公式表 ⭐(必须背)
| $f(x)$ | $f'(x)$ |
|---|---|
| $C$(常数) | $0$ |
| $x^n$ | $nx^{n-1}$ |
| $\sin x$ | $\cos x$ |
| $\cos x$ | $-\sin x$ |
| $\tan x$ | $\frac{1}{\cos^2 x} = \sec^2 x$ |
| $e^x$ | $e^x$ |
| $a^x$ | $a^x \ln a$ |
| $\ln x$ | $\frac{1}{x}$ |
| $\log_a x$ | $\frac{1}{x\ln a}$ |
| $\arcsin x$ | $\frac{1}{\sqrt{1-x^2}}$ |
| $\arctan x$ | $\frac{1}{1+x^2}$ |
💡 记忆要点:
- 幂函数:指数降 1,原指数提到前面
- $e^x$ 是唯一"导数等于自己"的函数(这条很重要,后续解微分方程会用到)
3 可导与连续的关系 ⭐
定理:可导 ⟹ 连续(可导更强)
反之不成立:连续不一定可导。
经典反例:$f(x) = |x|$ 在 $x=0$ 处
- 连续吗?是的,图像不断
- 可导吗?不可导
为什么:用定义算
$$\lim_{\Delta x\to0^+}\frac{|0+\Delta x|-|0|}{\Delta x} = \frac{\Delta x}{\Delta x} = 1$$
$$\lim_{\Delta x\to0^-}\frac{|\Delta x|}{\Delta x} = \frac{-\Delta x}{\Delta x} = -1$$
左右极限不等 → 导数不存在。
几何上:$|x|$ 在 $x=0$ 处有个尖角,切线有"两种方向",不唯一。
⚠️ 常见错误:以为"连续就能求导"。
记住:连续是"不断",可导是"光滑"。
4 微分
定义:$dy = f'(x)\,dx$
意义:当 $x$ 变化 $dx$ 时,$y$ 变化量的线性主部。
几何:微分是切线上的增量,$\Delta y$ 是曲线上的增量。$dx$ 越小时两者越接近。
可微 ⟺ 可导(一元函数中这两件事等价)。
近似计算的应用:
$$f(x_0 + \Delta x) \approx f(x_0) + f'(x_0)\Delta x$$
例:估算 $\sqrt{4.02}$
取 $f(x)=\sqrt{x}$,$x_0=4$,$\Delta x = 0.02$
$f(4)=2$,$f'(x)=\frac{1}{2\sqrt{x}}$,$f'(4)=\frac14$
$\sqrt{4.02} \approx 2 + \frac14 \times 0.02 = 2.005$真实值 2.004995… ✓ 非常接近
5 数学作业 S3
- [ ] 1. 用定义求 $f(x)=x^2+3x$ 的导数
- [ ] 2. 用定义求 $f(x)=\frac{1}{x}$ 的导数(提示:通分)
- [ ] 3. 用定义求 $f(x)=\sqrt{x+1}$ 的导数(提示:有理化)
- [ ] 4. 默写基本求导公式表(幂、指、对、三角)
- [ ] 5. 判断"连续是否一定可导",并举出一个反例,说明为什么它不可导
- [ ] 6. 求 $f(x)=|x-2|$ 在 $x=2$ 处是否可导(用左右导数说明)
- [ ] 7. 用微分估算 $\sqrt{9.05}$(提示:取 $x_0=9$)
- [ ] 8.(Python)用数值差分近似导数,和解析结果对比,找出误差最小的 h
第 8 题参考代码:
import numpy as np
x0 = 3.0
真实值 = 2 * x0 # f(x)=x² 在 x=3 处的导数 = 6
for h in [1e-2, 1e-4, 1e-6, 1e-8, 1e-10, 1e-12, 1e-15]:
近似 = ((x0 + h)**2 - x0**2) / h
print(f"h={h:<8} 近似={近似:<20.10f} 误差={abs(近似 - 真实值):.3e}")
你会看到一张"两头翘"的表,误差先变小、后变大:
$h$ 误差 $10^{-2}$ $10^{-2}$ $10^{-6}$ $10^{-6}$ $10^{-8}$ $\mathbf{4\times10^{-8}}$ ← 最好 $10^{-10}$ $5\times10^{-7}$ $10^{-12}$ $5\times10^{-4}$ $10^{-15}$ $0.67$ ← 彻底崩了 为什么会两头翘:
- h 太大 → 差商本身就是近似的,截断误差大(误差 $\approx h$)
- h 太小 → $(x+h)^2$ 和 $x^2$ 两个数非常接近,相减时前面的有效数字被吃掉了,
剩下的全是噪声,舍入误差大(误差 $\approx \frac{\text{机器精度}}{h}$)这叫灾难性抵消。最佳 h 在两者相交处,大约 $10^{-8}$。
⚠️ 有一个前提:上面能出现"h 太小反而崩",要求 $f(x_0) \ne 0$。
像上面这样 $f(3)=9 \ne 0$,相减的两个数才真正接近,抵消才会发生。
如果换成在 $x_0=0$ 处测 $\sin x$($\sin 0 = 0$),分子就是 $\sin h - 0$,
没有抵消,h 小到 $10^{-16}$ 也依然准确——现象不会出现。
所以别用那个点做验证,会以为讲义写错了。💡 意义:这是数值计算的第一课,"把公式直接翻译成代码"经常不work。
后面学数值方法(数值积分、解方程)时会反复遇到这个权衡。
第二部分 · 编程
6 for 循环
最常用的循环,对一堆东西,每个都做一遍。
for i in range(5):
print(i)
# 输出:0 1 2 3 4(注意:不含 5!)
range() 的三种用法:
range(5) # 0,1,2,3,4
range(2, 6) # 2,3,4,5 (含起点,不含终点)
range(0, 10, 3) # 0,3,6,9 (步长为 3)
range(10, 0, -1) # 10,9,...,1 (倒着数)
⚠️
range(n)不含 n。这是最常见的 off-by-one(差一)错误来源。
遍历列表:
fruits = ["苹果", "香蕉", "橙子"]
for fruit in fruits:
print(f"我喜欢{fruit}")
同时要索引和值(用 enumerate):
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 0: 苹果
# 1: 香蕉
# 2: 橙子
累加模式(非常常见):
total = 0
for i in range(1, 101):
total += i
print(total) # 5050
💡
total += i是total = total + i的简写。-=*=/=同理。
7 while 循环
用于"不知道要循环多少次"的情况。
count = 0
while count < 5:
print(count)
count += 1
⚠️ 一定要让条件有机会变假!否则就是死循环。
上面如果忘了
count += 1,程序会永远打印 0。
典型用法:直到满足条件为止
secret = 7
guess = 0
while guess != secret:
guess = int(input("猜一个数字:"))
if guess < secret:
print("小了")
elif guess > secret:
print("大了")
print("猜对了!")
8 break 和 continue
| 关键字 | 作用 |
|---|---|
break |
跳出整个循环 |
continue |
跳过本次,进入下一次 |
# break:找到就停
for i in range(1, 100):
if i * i > 50:
print(f"第一个平方大于50的是 {i}")
break
# 输出:第一个平方大于50的是 8
# continue:跳过偶数
for i in range(10):
if i % 2 == 0:
continue # 跳过本次
print(i)
# 输出:1 3 5 7 9
break 常用在"搜索"场景:
found = False
for x in data:
if condition(x):
found = True
break
9 循环嵌套
for i in range(1, 4):
for j in range(1, 4):
print(f"{i}×{j}={i*j}", end=" ")
print() # 换行
输出:
1×1=1 1×2=2 1×3=3
2×1=2 2×2=4 2×3=6
3×1=3 3×2=6 3×3=9
print()不传参数就输出一个换行。
end=" "表示"输出完不换行,而是加两个空格"。💡 理解嵌套:外层跑一次,内层跑一整轮。
上面的例子:外层i变化 3 次,每次内层j都跑 3 次 → 共 9 次。
10 死循环与怎么逃出来 ⚠️
while True:
print("按 Ctrl+C 才能停下我")
在 Jupyter / 终端里,按 Ctrl + C(Windows 是 Ctrl + C 或 Ctrl + F2)可以中断。
💡 你一定会不小心写出死循环,
知道怎么逃出来才不会被卡住。
合法的死循环(配合 break 使用):
while True:
cmd = input("输入命令(q 退出):")
if cmd == "q":
break
print(f"执行:{cmd}")
这是"命令行菜单"的标准写法。
11 🔧 技能卡 3:循环出错,怎么查
循环的 bug 有个特点:它跑完了、没报错、但结果不对。这时候没有 traceback 可读,得靠自己。
11.1 四步排查法
① 先确认它到底跑没跑
for i in range(5):
print("进来了", i) # ← 如果一行都没打印,说明循环根本没进去
② 把范围缩小再看
把 range(1, 100) 临时改成 range(1, 5),看前几轮到底发生了什么。
💡 这招叫缩小输入,是定位 bug 最有效的手段,也就是阶段 2 学的二分法思想:
每次排除一半,很快锁定问题在哪。小数据看逻辑,大数据看性能。
③ 每轮打印关键变量
total = 0
for i in range(1, 6):
total += i
print(f"i={i} total={total}") # ← 盯住每一轮的变化
④ 检查边界(off-by-one)
range(5) 只到 4,不含 5。这类"差一"错误是循环里最常见的 bug。
# 想算 1 到 5 的和,这样写漏了 5!
for i in range(5): # 0,1,2,3,4 ← 少了 5,还多了 0
total += i
11.2 循环专属的坑
| 现象 | 原因 |
|---|---|
| 循环体一次都没执行 | 条件一开始就是假;或 range 是空的 |
| 少算/多算一次 | off-by-one,range 不含终点 |
| 死循环卡住 | while 的条件永远为真;按 Ctrl+C 退出 |
| 累加结果不对 | 累加变量忘了初始化(total = 0 写在循环外) |
⚠️ 最容易犯的:累加变量初始化写在了循环里面。
for i in range(1, 6):
total = 0 # ❌ 每轮都被清零,最后只剩最后一个数
total += i
初始化必须在循环外面。
12 🧠 这跟认知科学有什么关系
概念性内容,无法用代码验证,请对照文献。
导数 ↔ 学习曲线的"进步速度"。
把"练习次数"当自变量 $x$,"成绩"当因变量 $f(x)$,那么导数 $f'(x)$ 就是"进步速度"。
技能习得有个著名规律:进步速度随练习递减。也就是说:
$$f'(x) \text{ 本身在减小} \quad\Longleftrightarrow\quad f''(x) < 0$$
也就是说,学习曲线的形状是"先陡后平",开头涨得快,后来越来越平。
怎么在图上认出来:曲线像一个拱形(∩),越往右越平。
阶段 7 会给它一个正式名字(凹凸性),注意那个名字在不同教材里叫法相反,
到时我会专门提醒。现在你只要记住形状:先陡后平。
这解释了"边际收益递减":练习当然有用,只是同样的练习量,带来的提升越来越小。
这个现象在你自己身上就能观察到:第 1 小时学打字进步巨大,第 100 小时几乎看不出变化。
💡 对你有实际用处:既然学习曲线是先陡后平,那"每天 1 小时 × 7 天"和"7 小时 × 1 天"
在同一个阶段效果接近,但间隔重复能让曲线整体上移(记忆保持更久)。
这就是后面要讲的"分散练习优于集中练习"。
数值差分 ↔ 实验数据求变化率。
实验测出来的曲线是离散的点(每次试验一个数据点),没有解析表达式。
想求它的变化率,只能像第 8 题那样用差分近似导数——这就是科研里"算梯度"的实际做法。
⚠️ 诚实说明:上面"学习曲线先陡后平"是经验规律 + 常见模型(幂律、指数模型),
不是从公理推出的定理。不同任务、不同被试,曲线形状会变。
数学部分($f''<0$ 意味着导数递减)我能保证;认知部分请以文献为准。
13 编程作业 S3
- [ ] 1. 打印 1–100 的和(用
for) - [ ] 2. 打印九九乘法表(用嵌套循环)
- [ ] 3. 判断并打印 100 以内的所有素数
- [ ] 4. 用
while写一个程序:不断输入数字,直到输入 0 为止,最后输出所有数字的和 - [ ] 5. 写一个猜数字游戏:程序想一个 1–100 的数,用户猜,提示"大了/小了",猜中后告诉用户猜了几次
- [ ] 6. 陷阱体验:写一个
while True:的死循环,用Ctrl+C中断它 - [ ] 7. 打印斐波那契数列的前 20 项
- [ ] 8.(技能)下面这段代码"想算 1–10 的平方和",但结果是错的。
先用技能卡 3 的四步法定位,说清楚错在哪,再改对。
第 8 题的代码(先别跑,先自己读出来错在哪):
for i in range(1, 11):
total = 0
total += i * i
print(total)
正确答案是 385。读完之后再跑一遍验证你的判断。
第 3 题提示(素数判断):
for n in range(2, 101):
is_prime = True
for d in range(2, n):
if n % d == 0:
is_prime = False
break # 找到一个因子就够了
if is_prime:
print(n, end=" ")
第 7 题提示:
a, b = 1, 1 # 一行同时给两个变量赋值
for _ in range(20):
print(a, end=" ")
a, b = b, a + b
a, b = b, a + b是 Python 的优雅写法:
等号右边的两个值先全部算好,然后才赋给左边。
所以这里不需要临时变量,a + b用的是旧的a。对比一下其他语言的写法(要先存个临时变量):
temp = a + b
a = b
b = temp
术语上这叫"同时赋值"(背后用到的是元组,阶段 9 会正式讲)。
现在你只要记住右边先算完、再赋值这一条规律就够用。下划线
_表示"我不关心这个循环变量"(这里只是要循环 20 次)。
本阶段自评
- 数学:导数的几何意义是什么?为什么 $|x|$ 在 0 处不可导?
- 数学:$e^x$ 的导数是什么?(它有个独特性质,是什么?)
- 数学:为什么 h 太小反而让数值导数更不准?什么条件下才会出现这个现象?
- 编程:
range(1, 5)会生成哪些数?range(0, 10, 2)呢? - 编程:
break和continue的区别是什么? - 技能:循环跑了但结果不对,第一步该做什么?
- 连接:为什么说"进步速度递减"等价于"学习曲线先陡后平"?
- 动手:第 6 题做了吗?你成功从死循环里逃出来了吗?
全部答得上 → 进阶段 4。