第 3 章 向量的加法、减法与数乘
学习目标
- 掌握向量加法的两种几何法则:三角形法则、平行四边形法则
- 掌握加法、减法、数乘的分量计算公式
- 理解数乘如何改变向量的大小与方向
- 会用 NumPy 与 PyTorch 做向量运算,并用 matplotlib 验证几何意义
- 理解向量运算的运算律(交换律、结合律、分配律)
3.1 从位移到加法:先走一段,再走一段
小明的家在 点。他先向东走 3 千米到 点,再向北走 2 千米到 点。问:他最终的位置相对家来说,在哪里?
第一步的位移是向量 ,第二步的位移是向量 。两步合起来的效果,等于从 直接走到 的位移:
这就是向量加法:把两个位移「接起来」,得到总位移。

几何上,向量加法有两种画法:
- 三角形法则:把 的起点放在 的终点上,「首尾相接」,从 的起点连到 的终点,得到 。
- 平行四边形法则:把 、 放在同一起点,以它们为邻边作平行四边形,从起点出发的那条对角线就是 。
两种画法得到同一个结果——这本身就是向量加法交换律的几何证明(见 3.4)。
3.2 分量加法:横加横,纵加纵
把向量写成坐标,加法就变成「对应分量相加」:
为什么可以这样加?因为横方向与纵方向互相独立:向东 3 千米的横位移是 3,向北 2 千米的横位移是 0,横方向总共移动 ;纵方向总共移动 。分量各自相加,再合成。
NumPy 与 PyTorch 里,加法就是数组相加:
python
import numpy as np
u = np.array([3.0, 0.0]) # 先向东 3
w = np.array([0.0, 2.0]) # 再向北 2
print("u + w =", u + w)运行输出:
text
u + w = [3. 2.]python
import torch
u = torch.tensor([3.0, 0.0])
w = torch.tensor([0.0, 2.0])
print("torch u + w =", u + w)运行输出:
text
torch u + w = tensor([3., 2.])3.3 减法:加上负向量
向量减法定义为「加上负向量」:
即对应分量相减。
几何上, 是从 的终点指向 的终点的那条有向线段(把两个向量起点放一起)。它的直观含义是「从 的位置,到 的位置,该怎么走」。
python
import numpy as np
u = np.array([3.0, 2.0])
w = np.array([1.0, 4.0])
print("u - w =", u - w)
print("-w =", -w)
print("u + (-w) =", u + (-w))运行输出:
text
u - w = [ 2. -2.]
-w = [-1. -4.]
u + (-w) = [ 2. -2.]3.4 数乘:把向量拉长、压短或反向
数乘:数 乘向量 ,得到
它的效果是:
- :方向不变,长度变成原来的 倍;
- :方向不变,长度变成原来的 倍(缩短);
- :方向相反,长度变成原来的 倍;
- :得到零向量。

python
import numpy as np
v = np.array([2.0, 1.0])
print("2v =", 2 * v) # 同向,2 倍长
print("0.5v =", 0.5 * v) # 同向,一半长
print("-1v =", -1 * v) # 反向,一样长
print("0v =", 0 * v) # 零向量运行输出:
text
2v = [4. 2.]
0.5v = [1. 0.5]
-1v = [-2. -1.]
0v = [0. 0.]「乘 」对应的实际场景:同样的方向、把速度调到 倍;或者「往反方向走」。数乘让我们能伸缩和翻转向量,这是第 7 章矩阵变换的雏形。
3.5 运算律:为什么可以放心交换顺序
向量的加法与数乘满足下面五条基本运算律(标量 为任意数):
- 加法交换律:
- 加法结合律:
- 数乘分配律(对向量加法):
- 数乘分配律(对数的加法):
- 数乘结合律:
这些律不是「背下来就完了」,而是可以逐分量验证的。比如交换律:
因为数的加法满足 与 ,所以两个向量相等。其余各条同理——向量的运算律,最终都归结为数的运算律在每一个分量上成立。
用代码验证三条关键律:
python
import numpy as np
u = np.array([1.0, 2.0])
w = np.array([3.0, -1.0])
z = np.array([-2.0, 4.0])
k, l = 2.0, 3.0
print("交换律:", np.allclose(u + w, w + u))
print("结合律:", np.allclose((u + w) + z, u + (w + z)))
print("分配律1:", np.allclose(k * (u + w), k * u + k * w))
print("分配律2:", np.allclose((k + l) * u, k * u + l * u))
print("结合律(数乘):", np.allclose(k * (l * u), (k * l) * u))运行输出:
text
交换律: True
结合律: True
分配律1: True
分配律2: True
结合律(数乘): Truenp.allclose 用来比较浮点数组是否「几乎相等」——因为计算机里小数有舍入误差,直接比较 == 可能因为 这类问题误报。
3.6 画图验证:平行四边形法则
把 3.1 的加法画出来,同时画出数乘:
python
import matplotlib.pyplot as plt
from matplotlib import font_manager
for f in font_manager.findSystemFonts():
if any(k in f for k in ("NotoSansCJK", "NotoSansSC", "wqy", "SimHei", "msyh", "PingFang")):
font_manager.fontManager.addfont(f)
plt.rcParams["font.sans-serif"] = ["Noto Sans CJK SC", "WenQuanYi Zen Hei", "SimHei", "Microsoft YaHei", "PingFang SC"]
plt.rcParams["axes.unicode_minus"] = False
import numpy as np
u = np.array([3.0, 0.0])
w = np.array([0.0, 2.0])
fig, ax = plt.subplots(figsize=(6.5, 5.5))
ax.axhline(0, color="black", linewidth=1)
ax.axvline(0, color="black", linewidth=1)
ax.grid(True, linestyle=":", alpha=0.5)
ax.set_xlim(-0.5, 4.5)
ax.set_ylim(-0.5, 3.5)
ax.set_aspect("equal")
def arrow(vec, start, color, label=None):
ax.quiver(start[0], start[1], vec[0], vec[1],
angles="xy", scale_units="xy", scale=1, color=color, width=0.015)
if label:
ax.annotate(label, start + vec / 2, textcoords="offset points",
xytext=(8, 6), color=color)
arrow(u, np.array([0.0, 0.0]), "tab:red", "u")
arrow(w, u, "tab:blue", "w") # 首尾相接:w 起点在 u 终点
arrow(u + w, np.array([0.0, 0.0]), "tab:purple", "u + w") # 总位移
# 平行四边形补全(虚线):从 w 终点出发画 u
ax.plot([w[0], w[0] + u[0]], [w[1], w[1] + u[1]], color="tab:red",
linestyle="--", linewidth=1)
ax.plot([u[0], u[0] + w[0]], [u[1], u[1] + w[1]], color="tab:blue",
linestyle="--", linewidth=1)
ax.set_title("向量加法:三角形法则 = 平行四边形法则")
fig.savefig("book/public/figs/fig03-vector_add.png", dpi=120, bbox_inches="tight")
plt.close(fig)
# 数乘图
fig, ax = plt.subplots(figsize=(6, 6))
ax.axhline(0, color="black", linewidth=1)
ax.axvline(0, color="black", linewidth=1)
ax.grid(True, linestyle=":", alpha=0.5)
ax.set_xlim(-4.5, 5.5)
ax.set_ylim(-2.5, 3.5)
ax.set_aspect("equal")
v = np.array([2.0, 1.0])
arrow(v, np.array([0.0, 0.0]), "tab:red", "v")
arrow(2 * v, np.array([0.0, 0.0]), "tab:blue", "2v")
arrow(0.5 * v, np.array([0.0, 0.0]), "tab:green", "0.5v")
arrow(-v, np.array([0.0, 0.0]), "tab:orange", "-v")
ax.set_title("数乘:拉长、缩短、反向")
fig.savefig("book/public/figs/fig03-scalar_mult.png", dpi=120, bbox_inches="tight")
plt.close(fig)
print("已保存两张图")动手实践
- 用三角形法则画出 与 的和,再用分量公式计算并验证。
- 在纸上画 ,画出 、 与 并判断后者的结果。
- 用 NumPy 计算 ,其中 、、,再用 PyTorch 算一遍对比结果。
- 修改 3.6 的代码,把 改成 ,观察平行四边形变成什么形状,并解释为什么。
常见错误
| 错误写法/理解 | 原因 |
|---|---|
| 把 的 也当分量加进去,如 | 数乘是每个分量都乘 : |
| 减法方向搞反, 画成从 终点到 终点 | 减法对应「从 的位置到 的位置」,箭头指向被减向量 |
| 认为 时长度变负 | 长度永远是正的, 只是方向反转,长度是 倍 |
直接用 == 比较浮点数组 | 浮点有舍入误差,应使用 np.allclose |
章末练习
基础
- 计算:、、、。
- 画出 、 与 ,标注每个向量。
- 用 NumPy 验证:(任选一组非零向量)。
提高
- 已知 且 ,求 ,并写出推导过程。
- 一个物体同时受到两个力:向右 4 牛、向上 3 牛。用向量加法求合力的大小与方向(方向用与水平方向的夹角描述,可先用勾股定理算大小,夹角留到第 4 章精确计算)。
挑战
- 对任意向量 , 对吗?用分量证明,再用代码验证。
- 用结合律解释:为什么先走 再走 再走 的总位移,与「三步合并成一步」的结果相同?写出对应的向量等式。
章末自测
- A.
- B.
- C.
- D.
- A.
- B.
- C.
- D.
- A.
- B.
- C.
- D.
- A.
- B.
- C.
- D.
- 向量加法满足交换律,意思是?
- A.
- B.
- C.
- D.
- 三角形法则中,两个向量如何摆放?
- A. 同一个起点
- B. 首尾相接
- C. 相互垂直
- D. 平行
- 等价于?
- A.
- B.
- C.
- D.
- 向量 ,则 是?
- A.
- B.
- C.
- D.
- 下列哪条是数乘分配律?
- A.
- B.
- C.
- D.
- 浮点数组比较应该用?
- A.
== - B.
np.allclose - C.
is - D.
>=
- A.
