Skip to content

第 1 章 从算术到函数 ​

学习目标 ​

  • 理解变量与代数式,会代入求值
  • 理解函数的定义:一台「输入 → 输出」的机器
  • 会画一次函数、二次函数的图像
  • 理解一次函数的斜率与截距
  • 理解平均变化率(割线的斜率)
  • 会用 NumPy 批量计算函数值,用 matplotlib 画函数图像

1.1 变量与代数式 ​

小学里学的算术,数字都是具体的:,。可是生活里有很多数是不确定的:一本书多少钱?一块橡皮多少钱?总价会随单价变化。为了表示「还不确定的数」,数学里用字母代表它,这个字母叫变量。

变量:一个可以取不同数值的字母或符号。

比如一支笔 元,买 3 支要 元。这里的 是变量, 叫代数式:用运算符号把数、字母连接起来的式子。把 的具体值代进去计算,叫代入求值:

注意代数式里的书写约定: 表示「3 乘以 x」,乘号省略不写; 表示「x 乘以 x」。

再看一个例子。正方形边长记作 ,那么:

  • 周长
  • 面积

当 时,代入得 、。同一个式子,换一个 就得到另一个结果,这就是「代数」和「算术」的区别:算术算的是具体的数,代数研究的是「式子怎么随变量变化」。

1.2 函数:一台「输入 → 输出」的机器 ​

把「代数式」升级一下:先给一个数 ,按一套固定的运算,得到一个数 。这套固定的规则,就叫函数。

函数(function):对于每一个输入 ,按照确定的规则,恰好得到一个输出 ,记作

读作「 等于 在 处的值」。 是规则的名字,括号里的 是输入。

函数有三个关键词,缺一不可:

  1. 每一个输入都有输出:不能「有的输入算不出结果」;
  2. 恰好一个输出:同一个输入不能给出两个不同的输出;
  3. 规则确定:同样的输入,永远得到同样的输出。

生活中的例子:

  • 温度换算:,把摄氏度 变成华氏度。 时,,水在 1 个标准大气压下沸腾。
  • 正方形面积:。 是边长,面积由边长唯一决定。
  • 出租车计价:起步价 13 元,之后每公里 2.3 元,,其中 是行驶公里数。

函数还有三个「零件」,合称三要素:

  • 定义域:允许的输入 的全体。比如面积 ,边长不能是负数,定义域是 。本书默认:定义域是「让式子有意义的所有实数」。
  • 对应法则:把输入变成输出的规则,即式子本身。
  • 值域:所有可能的输出 的全体。

为什么函数的输出必须唯一? 因为现实里的「因果关系」就是这样:同一个原因不会产生两个不同结果。今天 37°C 不会既是 98.6°F 又是 100°F。数学把这种「确定性」提炼成函数的概念,后面学导数、积分时,处处都要用到「函数值唯一」。

1.3 函数的图像:把「对应关系」画出来 ​

一个函数有一大堆输入输出对 :输入 得到 ,输入 得到 ……把它们全部画在坐标平面上,就得到函数的图像。

先回顾坐标平面(从小学基础出发,这里补全细节):

  • 两条数轴垂直交叉:横的叫 轴,竖的叫 轴;
  • 交点叫原点 ;
  • 点 :先沿 轴走横坐标这么多格,再沿 轴走纵坐标这么多格。

描点法画函数图像,只有三步:

  1. 取几个 (要覆盖不同位置,包括负数);
  2. 逐个算出 ;
  3. 把点 标出来,用平滑的线连起来。

以 为例,列出函数值表:

这些点关于 轴对称,连起来是向上开口的抛物线。为什么 和 的函数值相等?因为 ,两个负数相乘得正数。这条曲线后面会反复出现。

用 NumPy 一次算出整张表,再用 matplotlib 画图:

python
import numpy as np

x = np.array([-2, -1, 0, 1, 2])
f = x ** 2
print("x   =", x)
print("x²  =", f)
text
x   = [-2 -1  0  1  2]
x²  = [4 1 0 1 4]

NumPy 里的 x ** 2 对数组里的每一个数分别做平方,这正是函数的批量运算:一个数组进来,一个数组出去,每个输入对应唯一输出。

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

x = np.linspace(-2.5, 2.5, 300)
f = x ** 2

fig, ax = plt.subplots(figsize=(6, 5))
ax.plot(x, f, color="tab:blue", label="f(x) = x²")
ax.axhline(0, color="black", linewidth=0.8)
ax.axvline(0, color="black", linewidth=0.8)
ax.scatter([-2, -1, 0, 1, 2], [4, 1, 0, 1, 4], color="tab:red", zorder=3)
ax.set_xlim(-3, 3)
ax.set_ylim(-1, 6)
ax.set_aspect("equal")
ax.grid(True, linestyle=":", alpha=0.5)
ax.legend()
ax.set_title("函数图像:描点 f(x) = x²")
fig.savefig("book/public/figs/fig01-quadratic.png", dpi=120, bbox_inches="tight")
plt.close(fig)

二次函数图像

1.4 一次函数与斜率 ​

一次函数:形如

的函数(、 是常数,)。它的图像是一条直线,所以也叫线性函数。

名字里的「一次」,指的是 的次数是 1()。 叫斜率, 叫纵截距。

纵截距:图像与 轴交点的纵坐标。因为当 时,,所以交点就是 。

斜率衡量直线的倾斜程度,定义是「纵坐标的变化量 ÷ 横坐标的变化量」:

符号 (读作 delta)表示「变化量」: 是纵坐标的变化, 是横坐标的变化。

推导:直线上任取两点 、,既然它们都在直线 上,就都有:

用第二个式子减第一个式子:

这里用了三个规则: 消去截距;分配律 反过来用。两边除以 (要求 ,否则横坐标没变化、谈不上「倾斜」),就得到

斜率的几何含义:

  • :直线向右上方倾斜,越往右越高;
  • :直线向右下方倾斜,越往右越低;
  • 越大,直线越陡。

看 :斜率 ,截距 。取两点 和 验证:

与 一致。意思是:横坐标每增加 1, 增加 2。

python
x1, y1 = 1, 3
x2, y2 = 3, 7

k = (y2 - y1) / (x2 - x1)
print("斜率 k =", k)
text
斜率 k = 2.0

画出来看斜率与截距:

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

x = np.linspace(-1.5, 3.5, 300)
y = 2 * x + 1

fig, ax = plt.subplots(figsize=(7, 5))
ax.plot(x, y, color="tab:blue", label="y = 2x + 1")
ax.axhline(0, color="black", linewidth=0.8)
ax.axvline(0, color="black", linewidth=0.8)

# 两点与 Δx、Δy
p1, p2 = (1, 3), (3, 7)
ax.scatter([p1[0], p2[0]], [p1[1], p2[1]], color="tab:red", zorder=3)
ax.annotate("(1, 3)", p1, textcoords="offset points", xytext=(-18, -16), color="tab:red")
ax.annotate("(3, 7)", p2, textcoords="offset points", xytext=(8, -16), color="tab:red")
ax.annotate("", xy=p2, xytext=(p1[0], p1[1]),
            arrowprops=dict(arrowstyle="->", color="tab:green", lw=1.5))
ax.annotate("", xy=(p2[0], p1[1]), xytext=(p1[0], p1[1]),
            arrowprops=dict(arrowstyle="->", color="tab:orange", lw=1.5))
ax.text(2.05, 3.4, "Δy = 4", color="tab:green", fontsize=12)
ax.text(2.05, 2.4, "Δx = 2", color="tab:orange", fontsize=12)
ax.text(2.45, 5.4, "斜率 = Δy/Δx = 2", color="tab:blue", fontsize=12)

ax.set_xlim(-2, 4)
ax.set_ylim(-2, 9)
ax.set_aspect("equal")
ax.grid(True, linestyle=":", alpha=0.5)
ax.legend(loc="upper left")
ax.set_title("一次函数 y = 2x + 1:斜率与截距")
fig.savefig("book/public/figs/fig01-line.png", dpi=120, bbox_inches="tight")
plt.close(fig)

一次函数

1.5 平均变化率:任何函数的「斜率」 ​

不是所有函数都是直线。二次函数 (一辆车 小时开出的路程)的图像是弯曲的。弯曲的线没有「唯一的斜率」,但我们可以问:从 到 ,它平均每单位时间变化了多少?

平均变化率:函数 在区间 上的平均变化率定义为

它和一次函数斜率的公式一模一样,只是分子里的 、 换成了 、。

几何意义:连接图像上两点 、 的直线叫割线(secant),平均变化率就是这条割线的斜率。

算一下那辆车从 1 小时到 3 小时的平均速度:

「平均速度 80 km/h」不代表车一直开 80:它可能有时快有时慢,但「总路程 ÷ 总时间」这个整体平均值是 80。这正是下一章「瞬时速度」的出发点:把区间越缩越小,平均变化率会趋向一个极限。

python
def s(t):
    return 60 * t + 5 * t ** 2

v_avg = (s(3) - s(1)) / (3 - 1)
print("1 到 3 小时的平均速度 =", v_avg, "km/h")
text
1 到 3 小时的平均速度 = 80.0 km/h

画出路程曲线和割线,直观看到「平均变化率 = 割线斜率」:

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

def s(t):
    return 60 * t + 5 * t ** 2

t = np.linspace(0, 4, 300)
fig, ax = plt.subplots(figsize=(7, 5))
ax.plot(t, s(t), color="tab:blue", label="s(t) = 60t + 5t²")

t1, t2 = 1, 3
ax.plot([t1, t2], [s(t1), s(t2)], color="tab:red", linestyle="--", label="割线")
ax.scatter([t1, t2], [s(t1), s(t2)], color="tab:red", zorder=3)
ax.annotate("(1, 65)", (t1, s(t1)), textcoords="offset points", xytext=(10, -18), color="tab:red")
ax.annotate("(3, 225)", (t2, s(t2)), textcoords="offset points", xytext=(10, 6), color="tab:red")
ax.annotate("", xy=(t2, s(t1)), xytext=(t1, s(t1)),
            arrowprops=dict(arrowstyle="->", color="tab:orange", lw=1.5))
ax.annotate("", xy=(t2, s(t2)), xytext=(t2, s(t1)),
            arrowprops=dict(arrowstyle="->", color="tab:green", lw=1.5))
ax.text(1.35, 70, "Δt = 2", color="tab:orange", fontsize=12)
ax.text(2.45, 128, "Δs = 160", color="tab:green", fontsize=12)
ax.text(2.1, 105, "平均变化率 = 80", color="tab:red", fontsize=12)

ax.set_xlim(0, 4.4)
ax.set_ylim(0, 270)
ax.set_xlabel("时间 t(小时)")
ax.set_ylabel("路程 s(千米)")
ax.grid(True, linestyle=":", alpha=0.5)
ax.legend()
ax.set_title("平均变化率:割线的斜率")
fig.savefig("book/public/figs/fig01-avg_change.png", dpi=120, bbox_inches="tight")
plt.close(fig)

平均变化率

1.6 动手实践:温度换算表 ​

用函数 生成摄氏温度到华氏温度的换算表:

python
import numpy as np

def f(celsius):
    return 1.8 * celsius + 32

celsius = np.array([0, 20, 37, 100])
fahrenheit = f(celsius)
print("摄氏:", celsius)
print("华氏:", fahrenheit)
text
摄氏: [  0  20  37 100]
华氏: [ 32.   68.   98.6 212. ]

这张表验证了函数的两件事:每个输入恰好一个输出;同样的规则反复可用。 对应 (人体体温), 对应 (水的沸点)。

常见错误 ​

错误写法/理解原因
把 读成「3 和 x 相加」代数式里数字与字母并排表示相乘,
认为「输入一个数,函数可以给出两个输出」函数的定义要求输出唯一;否则就不是函数
斜率算成 斜率是「纵坐标变化 ÷ 横坐标变化」,分子分母不能颠倒
把平均变化率 写成 同样是「纵比横」;颠倒后单位都反了
取 代入斜率公式分母为 0,没有意义;斜率要求横坐标确实发生变化
matplotlib 图中中文显示为方块缺中文字体:按上文字体设置代码加载系统字体

章末练习 ​

基础

  1. 边长 的正方形,周长与面积各是多少?写出代数式再代入。
  2. 已知 ,求 、、。
  3. 求过 与 的直线的斜率,并写出这条直线的一次函数式。

提高

  1. 一次函数 过 与 :先用斜率公式求 ,再代入任一点求 ,写出完整的函数式。
  2. 自由落体路程 ( 秒,单位米)。求 2 秒到 4 秒的平均速度,写出每一步推导。

挑战

  1. 证明:任何一次函数 的任意两点算出的 都等于同一个常数 。
  2. 用 NumPy 生成 在 处的函数值表,并画出图像,观察它的最高点出现在哪个 附近。

章末自测 ​

每题选择一个最佳答案。本书不附答案:完成后交由老师或 AI 老师批改讲解。

  1. 一支笔 元,买 5 支,总价是?
    • A.
    • B.
    • C.
    • D.
  2. 中, 等于?
    • A.
    • B.
    • C.
    • D.
  3. 函数的定义要求:同一个输入必须得到?
    • A. 至少一个输出
    • B. 恰好一个输出
    • C. 两个输出
    • D. 输出比输入大
  4. 一次函数 的图像?
    • A. 向右上方倾斜
    • B. 向右下方倾斜
    • C. 水平
    • D. 竖直
  5. 直线 与 轴的交点是?
    • A.
    • B.
    • C.
    • D.
  6. 过 与 的直线,斜率是?
    • A.
    • B.
    • C.
    • D.
  7. 函数 在区间 上的平均变化率是 。若 、,平均变化率是?
    • A.
    • B.
    • C.
    • D.
  8. 平均变化率的几何意义是?
    • A. 切线的斜率
    • B. 割线的斜率
    • C. 曲线的高度
    • D. 曲线与 x 轴的交点
  9. NumPy 中,对数组 x 的每个元素求平方的写法是?
    • A. x * x
    • B. x ** 2
    • C. 两者都可以
    • D. 都不行
  10. 在 时的函数值 是?
    • A.
    • B.
    • C.
    • D.