第2章 基本结构 (Basic Structures: Sets, Functions, Sequences)
一、导读
1.1 本章学习目标
完成本章学习后,你将能够:
理解集合的基本概念,包括集合的表示、子集、并集、交集、差集和补集
掌握集合运算的性质和恒等式,能够运用文氏图进行可视化分析
理解函数的定义、类型(单射、满射、双射)及其在计算机科学中的应用
掌握序列和求和的概念,能够计算常见序列的和
理解可数集与不可数集的区别,了解康托尔对角线论证法
掌握笛卡尔积的概念及其在关系数据库中的应用
理解基数和序数的基本概念
将集合论思维应用于数据结构设计和算法分析
1.2 为什么本章如此重要
集合、函数和序列是离散数学中最基本的结构,它们构成了计算机科学的理论基础。
集合论是所有数学的基础语言。在计算机科学中,集合用于描述数据类型、状态空间、语言(形式语言理论)、数据库关系等。理解集合运算是理解更高级概念的前提。
函数是编程的核心抽象。每个函数都建立了输入域到输出域的映射。理解函数的性质(如单射、满射、双射)对于设计哈希函数、加密算法、数据压缩等有重要意义。
序列是数组、列表、字符串等数据结构的基础。理解序列的性质有助于分析算法的时间复杂度,设计高效的搜索和排序算法。
在数据库领域:关系模型建立在集合论基础上,SQL操作本质上是集合运算。理解这些概念有助于编写更高效的查询。
在编程语言理论中:类型系统可以用集合来描述,函数类型对应集合间的映射,泛型涉及集合的参数化。
在算法分析中:时间复杂度和空间复杂度本质上是对序列增长率的描述。大O记号描述了函数在无穷远处的行为。
1.3 核心问题引导
在学习本章之前,请思考以下问题:
空集是什么?为什么空集是任何集合的子集?
集合 {1, 2, 3} 和 {3, 2, 1} 是否相同?为什么?
什么是幂集?一个有n个元素的集合有多少个子集?
如何判断两个无限集合的大小是否相同?
为什么有些无限集比另一些无限集"更大"?
函数 f(x) = x² 是否是单射?是否是满射?这取决于什么?
序列 1, 1/2, 1/4, 1/8, ... 的和是多少?
有理数集和整数集哪个更大?有理数集和实数集哪个更大?
二、核心概念详解
2.1 集合 (Sets)
定义与直觉解释
集合是不同对象的无序聚集。这些对象称为集合的元素或成员。
关键特性:
- 无序性:{1, 2, 3} 和 {3, 1, 2} 是同一个集合
- 互异性:集合中的元素不重复,{1, 1, 2} 等同于 {1, 2}
- 确定性:对于任何对象,都能明确判断它是否属于该集合
集合的表示方法:
列举法:列出所有元素
- A = {1, 2, 3, 4, 5}
- B = {a, e, i, o, u}(英文元音字母)
描述法:用性质描述元素
- C = {x | x 是正偶数}
- D = {x ∈ ℝ | 0 ≤ x ≤ 1}
递归定义:通过规则生成元素
- 自然数集:0 ∈ ℕ;如果 n ∈ ℕ,则 n+1 ∈ ℕ
特殊集合:
- 空集 ∅ 或 {}:不包含任何元素的集合
- 全集 U:讨论范围内所有元素的集合
- 自然数集 ℕ = {0, 1, 2, 3, ...}
- 整数集 ℤ = {..., -2, -1, 0, 1, 2, ...}
- 有理数集 ℚ = {p/q | p, q ∈ ℤ, q ≠ 0}
- 实数集 ℝ:包括所有有理数和无理数
集合间的关系
子集:如果集合A的每个元素都是集合B的元素,则A是B的子集,记作 A ⊆ B。
形式化定义:A ⊆ B ⟺ ∀x (x ∈ A → x ∈ B)
真子集:如果 A ⊆ B 且 A ≠ B,则A是B的真子集,记作 A ⊂ B。
相等:A = B 当且仅当 A ⊆ B 且 B ⊆ A。即两个集合包含完全相同的元素。
重要定理:空集是任何集合的子集。
证明:要证明 ∅ ⊆ A,需要证明 ∀x (x ∈ ∅ → x ∈ A)。由于 x ∈ ∅ 永远为假,蕴含式 x ∈ ∅ → x ∈ A 永远为真(空真)。因此 ∅ ⊆ A。∎
集合运算
并集(Union):A ∪ B = {x | x ∈ A 或 x ∈ B}
交集(Intersection):A ∩ B = {x | x ∈ A 且 x ∈ B}
差集(Difference):A - B = {x | x ∈ A 且 x ∉ B},也记作 A \ B
补集(Complement):Ā = {x ∈ U | x ∉ A} = U - A
对称差(Symmetric Difference):A ⊕ B = (A - B) ∪ (B - A) = {x | x ∈ A 异或 x ∈ B}
示例:设 A = {1, 2, 3, 4}, B = {3, 4, 5, 6}
- A ∪ B = {1, 2, 3, 4, 5, 6}
- A ∩ B = {3, 4}
- A - B = {1, 2}
- B - A = {5, 6}
- A ⊕ B = {1, 2, 5, 6}
幂集
集合A的幂集 P(A) 是A的所有子集构成的集合。
示例:P({1, 2}) = {∅, {1}, {2}, {1, 2}}
定理:如果集合A有n个元素,则 P(A) 有 2ⁿ 个元素。
证明:对于A中的每个元素,在构造子集时有两种选择:包含或不包含。由乘法原理,总共有 2 × 2 × ... × 2 = 2ⁿ 种选择,每种选择对应一个唯一的子集。∎
集合恒等式
| 恒等式 | 公式 |
|---|---|
| 同一律 | A ∪ ∅ = A, A ∩ U = A |
| 支配律 | A ∪ U = U, A ∩ ∅ = ∅ |
| 幂等律 | A ∪ A = A, A ∩ A = A |
| 补集律 | A ∪ Ā = U, A ∩ Ā = ∅ |
| 交换律 | A ∪ B = B ∪ A, A ∩ B = B ∩ A |
| 结合律 | (A ∪ B) ∪ C = A ∪ (B ∪ C) |
| 分配律 | A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C) |
| 德摩根律 | $\overline{A \cup B} = \bar{A} \cap \bar{B}$ |
德摩根定律的证明:
证明 $\overline{A \cup B} = \bar{A} \cap \bar{B}$:
x ∈ $\overline{A \cup B}$
⟺ x ∉ A ∪ B
⟺ ¬(x ∈ A 或 x ∈ B)
⟺ x ∉ A 且 x ∉ B(德摩根律在命题逻辑中)
⟺ x ∈ Ā 且 x ∈ B̄
⟺ x ∈ Ā ∩ B̄
因此 $\overline{A \cup B} = \bar{A} \cap \bar{B}$。∎
2.2 函数 (Functions)
定义与直觉解释
函数 f 从集合A到集合B是一个规则,它为A中的每个元素恰好指定B中的一个元素。
记作:f: A → B
- 定义域(Domain):集合A
- 陪域(Codomain):集合B
- 值域(Range/Image):{f(a) | a ∈ A} ⊆ B
关键要求:
定义域中的每个元素都必须有像
每个元素的像是唯一的
示例:
- f: ℤ → ℤ, f(x) = x²
- 定义域:ℤ
- 陪域:ℤ
- 值域:{0, 1, 4, 9, 16, ...}(非负完全平方数)
函数的类型
单射(Injective/One-to-one):不同的输入产生不同的输出。
形式化定义:∀x₁, x₂ ∈ A, f(x₁) = f(x₂) → x₁ = x₂
等价地:∀x₁, x₂ ∈ A, x₁ ≠ x₂ → f(x₁) ≠ f(x₂)
示例:f: ℤ → ℤ, f(x) = 2x 是单射。
反例:f: ℤ → ℤ, f(x) = x² 不是单射,因为 f(-1) = f(1) = 1。
满射(Surjective/Onto):值域等于陪域。
形式化定义:∀b ∈ B, ∃a ∈ A 使得 f(a) = b
示例:f: ℤ → ℤ, f(x) = x + 1 是满射。
反例:f: ℤ → ℤ, f(x) = x² 不是满射,因为没有整数的平方等于-1。
双射(Bijective/One-to-one correspondence):既是单射又是满射。
双射函数存在逆函数 f⁻¹: B → A。
示例:f: ℤ → ℤ, f(x) = x + 1 是双射,其逆函数为 f⁻¹(y) = y - 1。
函数的复合
给定 f: A → B 和 g: B → C,它们的复合 g ∘ f: A → C 定义为:
(g ∘ f)(x) = g(f(x))
性质:
- 复合不满足交换律:一般 g ∘ f ≠ f ∘ g
- 复合满足结合律:h ∘ (g ∘ f) = (h ∘ g) ∘ f
特殊函数
恒等函数:id_A: A → A, id_A(x) = x
地板函数(向下取整):⌊x⌋ = 不超过x的最大整数
天花板函数(向上取整):⌈x⌉ = 不小于x的最小整数
阶乘函数:n! = 1 × 2 × 3 × ... × n,其中 0! = 1
模函数:a mod n = a 除以 n 的余数
2.3 序列与求和 (Sequences and Summations)
序列的定义
序列是从正整数集(或非负整数集)到某个集合S的函数。序列的第n项记作 aₙ。
表示方法:
- 列举法:1, 4, 9, 16, 25, ...
- 通项公式:aₙ = n²
- 递推关系:a₁ = 1, aₙ = aₙ₋₁ + 2n - 1
常见序列
算术序列:相邻项之差为常数d
- 通项:aₙ = a + (n-1)d
- 示例:2, 5, 8, 11, ...(a=2, d=3)
几何序列:相邻项之比为常数r
- 通项:aₙ = arⁿ⁻¹
- 示例:3, 6, 12, 24, ...(a=3, r=2)
斐波那契序列:
- F₀ = 0, F₁ = 1
- Fₙ = Fₙ₋₁ + Fₙ₋₂(n ≥ 2)
- 序列:0, 1, 1, 2, 3, 5, 8, 13, 21, ...
调和序列:
- aₙ = 1/n
- 序列:1, 1/2, 1/3, 1/4, ...
求和
序列 a₁, a₂, ..., aₙ 的和记作:
$$\sum_{i=1}^{n} a_i = a_1 + a_2 + ... + a_n$$
常用求和公式:
| 求和 | 公式 | ||
|---|---|---|---|
| 常数 | $\sum_{i=1}^{n} c = cn$ | ||
| 自然数 | $\sum_{i=1}^{n} i = \frac{n(n+1)}{2}$ | ||
| 平方和 | $\sum_{i=1}^{n} i^2 = \frac{n(n+1)(2n+1)}{6}$ | ||
| 立方和 | $\sum_{i=1}^{n} i^3 = \left[\frac{n(n+1)}{2}\right]^2$ | ||
| 几何级数 | $\sum_{i=0}^{n} r^i = \frac{r^{n+1}-1}{r-1}$(r ≠ 1) | ||
| 无穷几何级数 | $\sum_{i=0}^{\infty} r^i = \frac{1}{1-r}$( | r | < 1) |
几何级数求和公式的证明:
设 S = 1 + r + r² + ... + rⁿ
则 rS = r + r² + r³ + ... + rⁿ⁺¹
两式相减:S - rS = 1 - rⁿ⁺¹
即 S(1-r) = 1 - rⁿ⁺¹
因此 $S = \frac{1-r^{n+1}}{1-r} = \frac{r^{n+1}-1}{r-1}$ ∎
2.4 可数性 (Countability)
有限集与无限集
有限集:元素个数为自然数的集合。
无限集:不是有限集的集合。
基数
两个集合A和B有相同的基数(大小),如果存在从A到B的双射。
记作:|A| = |B|
有限集的基数:元素个数。
无限集的基数:
- 可数无限:与自然数集ℕ有相同基数的集合,记作 ℵ₀(阿列夫零)
- 不可数无限:基数大于 ℵ₀ 的集合
可数集
定理:正偶数集与ℕ有相同基数。
证明:定义 f: ℕ → {2, 4, 6, ...} 为 f(n) = 2n。这是双射。∎
这个结果令人惊讶:一个集合可以和它的真子集有相同的大小!这是无限集的特征。
定理:整数集ℤ是可数的。
证明:我们可以将整数排列为序列:0, 1, -1, 2, -2, 3, -3, ...
定义 f: ℕ → ℤ 为:
- f(2k) = k
- f(2k+1) = -(k+1)
这是双射。∎
定理:有理数集ℚ是可数的。
证明思路:将有理数排列成二维表格,然后按对角线遍历。虽然会有重复,但可以通过跳过已出现的数来获得双射。∎
不可数集
康托尔对角线论证:实数集ℝ是不可数的。
证明(针对[0,1]区间):
假设[0,1]区间的实数是可数的,可以将它们排列为序列 r₁, r₂, r₃, ...
将每个实数写成小数形式:
- r₁ = 0.d₁₁ d₁₂ d₁₃ ...
- r₂ = 0.d₂₁ d₂₂ d₂₃ ...
- r₃ = 0.d₃₁ d₃₂ d₃₃ ...
- ...
其中 dᵢⱼ 是第i个数的第j位小数。
构造一个新数 x = 0.x₁ x₂ x₃ ...,其中:
- xᵢ = 5 如果 dᵢᵢ ≠ 5
- xᵢ = 6 如果 dᵢᵢ = 5
x 与每个 rᵢ 至少在第i位不同,因此 x 不在列表中。这与列表包含所有[0,1]区间的实数矛盾。
因此[0,1]区间的实数是不可数的,从而ℝ也是不可数的。∎
连续统假设:不存在基数严格介于 ℵ₀ 和 |ℝ| 之间的集合。这个命题在标准集合论公理系统中既不能被证明也不能被证伪。
基数算术
对于无限基数,有以下性质:
- ℵ₀ + ℵ₀ = ℵ₀
- ℵ₀ × ℵ₀ = ℵ₀
- 2^ℵ₀ = |ℝ|(连续统的基数)
三、程序员的视角
3.1 在计算机科学中的应用
数据结构
- 集合:Python的set、Java的HashSet、C++的std::set
- 字典/映射:实现函数概念的键值对结构
- 数组/列表:序列的具体实现
- 位向量:用位串表示有限集合,支持高效的集合运算
数据库
关系数据库基于集合论:
- 表是元组的集合
- SELECT 操作对应选择(筛选行)
- PROJECT 操作对应投影(筛选列)
- UNION、INTERSECT、EXCEPT 对应集合运算
- JOIN 对应笛卡尔积的子集
-- 并集
SELECT name FROM table1 UNION SELECT name FROM table2;
-- 交集
SELECT name FROM table1 INTERSECT SELECT name FROM table2;
-- 差集
SELECT name FROM table1 EXCEPT SELECT name FROM table2;哈希函数
理想的哈希函数应该是单射(无冲突),但由于定义域通常大于陪域,这不可能实现。好的哈希函数应该尽量减少冲突。
复杂度分析
算法的时间复杂度描述了运行时间作为输入大小函数的增长率。大O记号本质上是描述函数集合:
O(f(n)) = {g(n) | ∃c > 0, ∃n₀, ∀n ≥ n₀, g(n) ≤ c·f(n)}
3.2 常见陷阱与误区
混淆 ∈ 和 ⊆
- ∈ 表示元素与集合的关系:1 ∈ {1, 2, 3}
- ⊆ 表示集合与集合的关系:{1} ⊆ {1, 2, 3}
注意:1 ⊆ {1, 2, 3} 是错误的写法。
空集的微妙性
- ∅ 是任何集合的子集
- {∅} 不是空集,它是一个包含一个元素(空集)的集合
- ∅ ∈ {∅} 为真,但 ∅ ∈ ∅ 为假
函数定义的完整性
在编程中,忘记处理某些输入情况会导致运行时错误。确保函数对定义域中的所有输入都有定义。
# 错误:未处理 x = 0 的情况
def reciprocal(x):
return 1 / x
# 正确:处理边界情况
def safe_reciprocal(x):
if x == 0:
raise ValueError("Cannot compute reciprocal of zero")
return 1 / x浮点数精度
实数在计算机中只能用有限精度的浮点数近似。这导致:
- 0.1 + 0.2 ≠ 0.3(精确相等)
- 累加大量小数时误差会累积
3.3 与其他层级的联系
- 硬件层:位运算直接对应集合运算(位向量表示集合)
- 操作系统层:文件权限集合、进程组
- 网络层:IP地址集合、路由表
- 应用层:用户组、标签系统、推荐系统的候选集
四、代码实战
4.1 集合运算实现
"""
集合运算的实现与演示
使用Python内置set类型,但展示底层原理
"""
class SetOperations:
"""集合运算工具类"""
@staticmethod
def union(set_a, set_b):
"""并集:A ∪ B"""
result = set(set_a) # 复制A
result.update(set_b) # 添加B的元素
return result
@staticmethod
def intersection(set_a, set_b):
"""交集:A ∩ B"""
result = set()
for elem in set_a:
if elem in set_b:
result.add(elem)
return result
@staticmethod
def difference(set_a, set_b):
"""差集:A - B"""
result = set()
for elem in set_a:
if elem not in set_b:
result.add(elem)
return result
@staticmethod
def symmetric_difference(set_a, set_b):
"""对称差:A ⊕ B"""
return SetOperations.difference(
SetOperations.union(set_a, set_b),
SetOperations.intersection(set_a, set_b)
)
@staticmethod
def is_subset(subset, superset):
"""判断是否为子集:subset ⊆ superset"""
for elem in subset:
if elem not in superset:
return False
return True
@staticmethod
def power_set(original_set):
"""幂集:P(A),返回所有子集的列表"""
elements = list(original_set)
n = len(elements)
result = []
# 使用位掩码枚举所有子集
for mask in range(2 ** n):
subset = set()
for i in range(n):
if mask & (1 << i):
subset.add(elements[i])
result.append(subset)
return result
@staticmethod
def cartesian_product(set_a, set_b):
"""笛卡尔积:A × B"""
result = set()
for a in set_a:
for b in set_b:
result.add((a, b))
return result
def demonstrate_set_operations():
"""演示集合运算"""
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(f"A = {A}")
print(f"B = {B}")
print(f"A ∪ B = {SetOperations.union(A, B)}")
print(f"A ∩ B = {SetOperations.intersection(A, B)}")
print(f"A - B = {SetOperations.difference(A, B)}")
print(f"B - A = {SetOperations.difference(B, A)}")
print(f"A ⊕ B = {SetOperations.symmetric_difference(A, B)}")
print(f"A ⊆ B? {SetOperations.is_subset(A, B)}")
print(f"{{1, 2}} ⊆ A? {SetOperations.is_subset({1, 2}, A)}")
print("\n幂集 P({{1, 2, 3}}):")
for subset in SetOperations.power_set({1, 2, 3}):
print(f" {subset}")
print(f"\n笛卡尔积 {{1, 2}} × {{'a', 'b'}}:")
for pair in SetOperations.cartesian_product({1, 2}, {'a', 'b'}):
print(f" {pair}")
if __name__ == "__main__":
demonstrate_set_operations()4.2 函数性质检查
"""
检查函数的单射性、满射性和双射性
"""
def is_injective(func, domain, codomain):
"""
检查函数是否为单射
参数:
func: 函数,接受domain中的元素,返回codomain中的元素
domain: 定义域(可迭代对象)
codomain: 陪域(可迭代对象)
返回:
bool: 是否为单射
"""
images = []
for x in domain:
fx = func(x)
if fx in images:
return False # 找到两个不同元素映射到同一值
images.append(fx)
return True
def is_surjective(func, domain, codomain):
"""
检查函数是否为满射
参数:
func: 函数
domain: 定义域
codomain: 陪域
返回:
bool: 是否为满射
"""
codomain_set = set(codomain)
image_set = set(func(x) for x in domain)
return codomain_set.issubset(image_set)
def is_bijective(func, domain, codomain):
"""检查函数是否为双射"""
return is_injective(func, domain, codomain) and \
is_surjective(func, domain, codomain)
def find_inverse(func, domain, codomain):
"""
寻找双射函数的逆函数
返回:
dict: 逆映射,或None如果函数不是双射
"""
if not is_bijective(func, domain, codomain):
return None
inverse = {}
for x in domain:
inverse[func(x)] = x
return inverse
def demonstrate_function_properties():
"""演示函数性质检查"""
# 示例1: f(x) = 2x, 从 {1,2,3} 到 {2,4,6,8}
domain1 = [1, 2, 3]
codomain1 = [2, 4, 6, 8]
func1 = lambda x: 2 * x
print("函数 f(x) = 2x, 定义域={1,2,3}, 陪域={2,4,6,8}")
print(f" 单射: {is_injective(func1, domain1, codomain1)}")
print(f" 满射: {is_surjective(func1, domain1, codomain1)}")
print(f" 双射: {is_bijective(func1, domain1, codomain1)}")
# 示例2: f(x) = x^2, 从 {-2,-1,0,1,2} 到 {0,1,2,3,4}
domain2 = [-2, -1, 0, 1, 2]
codomain2 = [0, 1, 2, 3, 4]
func2 = lambda x: x ** 2
print("\n函数 f(x) = x², 定义域={-2,-1,0,1,2}, 陪域={0,1,2,3,4}")
print(f" 单射: {is_injective(func2, domain2, codomain2)}")
print(f" 满射: {is_surjective(func2, domain2, codomain2)}")
print(f" 双射: {is_bijective(func2, domain2, codomain2)}")
# 示例3: f(x) = x + 1, 从 {0,1,2} 到 {1,2,3}
domain3 = [0, 1, 2]
codomain3 = [1, 2, 3]
func3 = lambda x: x + 1
print("\n函数 f(x) = x+1, 定义域={0,1,2}, 陪域={1,2,3}")
print(f" 单射: {is_injective(func3, domain3, codomain3)}")
print(f" 满射: {is_surjective(func3, domain3, codomain3)}")
print(f" 双射: {is_bijective(func3, domain3, codomain3)}")
inverse = find_inverse(func3, domain3, codomain3)
if inverse:
print(f" 逆函数: {inverse}")
if __name__ == "__main__":
demonstrate_function_properties()4.3 序列求和与收敛性
"""
序列求和与收敛性分析
"""
import math
def arithmetic_sum(a, d, n):
"""
算术序列求和
参数:
a: 首项
d: 公差
n: 项数
返回:
float: 前n项和
"""
return n * (2 * a + (n - 1) * d) / 2
def geometric_sum(a, r, n):
"""
几何序列求和
参数:
a: 首项
r: 公比
n: 项数
返回:
float: 前n项和
"""
if r == 1:
return a * n
return a * (1 - r ** n) / (1 - r)
def infinite_geometric_sum(a, r):
"""
无穷几何级数求和(仅当|r| < 1时收敛)
参数:
a: 首项
r: 公比
返回:
float or None: 和,如果不收敛则返回None
"""
if abs(r) >= 1:
return None
return a / (1 - r)
def harmonic_sum(n):
"""
调和序列求和
参数:
n: 项数
返回:
float: 前n项和
"""
return sum(1.0 / i for i in range(1, n + 1))
def fibonacci_sequence(n):
"""
生成斐波那契序列的前n项
参数:
n: 项数
返回:
list: 斐波那契数列
"""
if n <= 0:
return []
if n == 1:
return [0]
fib = [0, 1]
for i in range(2, n):
fib.append(fib[-1] + fib[-2])
return fib
def demonstrate_sequences():
"""演示序列求和"""
# 算术序列: 2, 5, 8, 11, ...
print("算术序列: 2, 5, 8, 11, ...")
print(f" 前10项和: {arithmetic_sum(2, 3, 10)}")
print(f" 验证: {sum(2 + 3*i for i in range(10))}")
# 几何序列: 3, 6, 12, 24, ...
print("\n几何序列: 3, 6, 12, 24, ...")
print(f" 前10项和: {geometric_sum(3, 2, 10)}")
print(f" 验证: {sum(3 * 2**i for i in range(10))}")
# 无穷几何级数: 1 + 1/2 + 1/4 + 1/8 + ...
print("\n无穷几何级数: 1 + 1/2 + 1/4 + 1/8 + ...")
print(f" 理论和: {infinite_geometric_sum(1, 0.5)}")
print(f" 前20项和: {geometric_sum(1, 0.5, 20)}")
# 调和序列
print("\n调和序列: 1 + 1/2 + 1/3 + 1/4 + ...")
for n in [10, 100, 1000, 10000]:
print(f" 前{n}项和: {harmonic_sum(n):.6f}")
print(" 注意: 调和级数发散(趋向无穷)")
# 斐波那契序列
print("\n斐波那契序列:")
fib = fibonacci_sequence(15)
print(f" 前15项: {fib}")
print(f" 前15项和: {sum(fib)}")
# 黄金比例与斐波那契
print("\n斐波那契比值趋近黄金比例:")
for i in range(2, 15):
ratio = fib[i] / fib[i-1] if fib[i-1] != 0 else float('inf')
print(f" F({i})/F({i-1}) = {fib[i]}/{fib[i-1]} ≈ {ratio:.6f}")
print(f" 黄金比例 φ = {(1 + math.sqrt(5)) / 2:.6f}")
if __name__ == "__main__":
demonstrate_sequences()五、深入思考
5.1 历史背景
集合论由德国数学家格奥尔格·康托尔(Georg Cantor, 1845-1918)在19世纪末创立。他的工作在当时引起巨大争议,因为无限集的性质违反直觉。然而,集合论最终成为现代数学的基础。
罗素悖论(1901年)揭示了朴素集合论的问题:考虑集合 R = {x | x ∉ x},那么 R ∈ R 吗?如果 R ∈ R,则根据定义 R ∉ R;如果 R ∉ R,则 R 应该属于 R。这个悖论促使数学家发展公理化集合论(如ZFC公理系统)来避免此类矛盾。
5.2 前沿方向
- 范畴论:提供比集合论更抽象的数学基础,在函数式编程中有应用
- 同伦类型论:结合类型论和同伦论的新兴基础理论
- 计算集合论:研究集合运算的高效算法
- 模糊集合:允许元素以某种程度属于集合,在人工智能中有应用
5.3 延伸阅读
- 《Naive Set Theory》by Paul R. Halmos
- 《Introduction to Set Theory》by Karel Hrbacek and Thomas Jech
- 《Concrete Mathematics》by Graham, Knuth, Patashnik
六、实验笔记
实验1:集合运算可视化
目标:实现一个能够绘制文氏图并执行集合运算的程序。
任务:
设计数据结构表示有限集合
实现所有基本集合运算(并、交、差、对称差、补集)
使用图形库(如matplotlib)绘制两个或三个集合的文氏图
在文氏图上高亮显示运算结果
验证集合恒等式(如德摩根定律)
测试用例:
- A = {1, 2, 3, 4}, B = {3, 4, 5, 6}
- 验证 A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C)
提交物:源代码、文氏图输出、验证报告。
实验2:可数性探索
目标:通过编程探索可数集的性质。
任务:
实现整数集到自然数集的双射
实现有理数的枚举(按对角线遍历)
验证康托尔配对函数:π(k₁, k₂) = (k₁ + k₂)(k₁ + k₂ + 1)/2 + k₂ 是 ℕ×ℕ 到 ℕ 的双射
尝试实现实数的近似表示,观察精度限制
(进阶)实现康托尔对角线论证的模拟
提交物:源代码、枚举结果、分析报告。
七、本章小结
本章介绍了离散数学的三个基本结构:集合、函数和序列。
集合是无序元素的聚集,集合运算包括并、交、差、补等。幂集包含所有子集,其大小是原集合大小的2的幂次。集合恒等式(如德摩根定律)在逻辑推理和电路设计中都有应用。
函数建立从一个集合到另一个集合的映射。单射保证不同输入产生不同输出,满射保证陪域中每个元素都有原像,双射同时满足两者且存在逆函数。函数的复合不满足交换律但满足结合律。
序列是有序的元素列表,可以是有限的或无限的。常见的序列包括算术序列、几何序列和斐波那契序列。求和公式使我们能够快速计算序列的和,而无需逐项相加。
可数性揭示了无限集的奇妙性质:有些无限集(如整数、有理数)是可数的,可以与自然数建立一一对应;而另一些无限集(如实数)是不可数的,严格大于可数无限。康托尔对角线论证是证明不可数性的经典方法。
这些基本概念为后续章节(关系、图、树等)奠定了基础,也是理解计算机科学核心理论的关键。
八、习题
习题1(基础):设 A = {1, 2, 3, 4, 5}, B = {3, 4, 5, 6, 7}, C = {5, 6, 7, 8, 9}。计算:
(a) A ∪ B
(b) A ∩ (B ∪ C)
(c) (A - B) ∪ (B - A)
(d) P(A) 的大小
习题2(基础):判断下列陈述的真假:
(a) ∅ ∈ {∅}
(b) ∅ ⊆ {∅}
(c) {∅} ⊆ ∅
(d) {{∅}} ⊆ {∅, {∅}}
习题3(中等):证明以下集合恒等式:
(a) A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C)
(b) A - (B ∪ C) = (A - B) ∩ (A - C)
(c) (A - B) - C = A - (B ∪ C)
习题4(中等):确定下列函数是否为单射、满射、双射:
(a) f: ℤ → ℤ, f(x) = x - 1
(b) f: ℤ → ℤ, f(x) = x² + 1
(c) f: ℤ⁺ → ℤ⁺, f(x) = x + 1
(d) f: ℝ → ℝ, f(x) = 2x - 3
习题5(中等):求下列和:
(a) $\sum_{i=1}^{100} (2i - 1)$
(b) $\sum_{i=0}^{10} 3 \cdot 2^i$
(c) $\sum_{i=1}^{n} i(i+1)$
习题6(较难):证明有理数集ℚ是可数的。(提示:将正有理数排列成二维表格,按对角线遍历)
习题7(较难):证明开区间(0, 1)与实数集ℝ有相同的基数。(提示:构造一个双射,如使用正切函数的变换)
习题8(挑战):施罗德-伯恩斯坦定理:如果存在单射 f: A → B 和单射 g: B → A,则存在双射 h: A → B。尝试证明这个定理或给出直观解释。
习题9(挑战):证明对于任何集合A,|A| < |P(A)|。(提示:假设存在双射,使用类似康托尔对角线的方法导出矛盾)
习题10(开放):研究并报告一个在实际应用中使用的特殊函数(如哈希函数、加密函数、激活函数等),分析其数学性质(是否为单射、满射、双射?)。