数学重学 - 00 数与运算

这是 数学重学路线图 阶段〇的子页面

数与运算

从最底层开始:数是什么,怎么算,为什么这样算


为什么要学这个

数和运算是整个数学大厦的地基

你写的每一行代码,底层都是数与运算

浮点数精度坑、整数溢出、位运算——这些工作中的”玄学 Bug”,根源都在这里

安全领域:密码学的本质就是数论运算

大数据领域:所有聚合操作(SUM/AVG/COUNT)都是算术运算的组合


核心概念:数的分类

数的大家庭(包含关系)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌─────────────────────────────────────────────┐
│ 实数 (Real) │
│ ┌──────────────────────┐ ┌──────────────┐ │
│ │ 有理数 (Rational) │ │ 无理数 │ │
│ │ ┌────────────────┐ │ │ (Irrational) │ │
│ │ │ 整数 (Integer) │ │ │ √2, π, e │ │
│ │ │ ┌────────────┐ │ │ │ │ │
│ │ │ │ 自然数 │ │ │ │ │ │
│ │ │ │ (Natural) │ │ │ │ │ │
│ │ │ │ 0,1,2,3... │ │ │ │ │ │
│ │ │ └────────────┘ │ │ │ │ │
│ │ │ ...,-2,-1,0, │ │ │ │ │
│ │ │ 1, 2, 3,... │ │ │ │ │
│ │ └────────────────┘ │ │ │ │
│ │ 1/2, -3/4, 0.75... │ │ │ │
│ └──────────────────────┘ └──────────────┘ │
└─────────────────────────────────────────────┘

自然数整数有理数实数

无理数和有理数合在一起 = 实数

各类数的直觉理解

自然数:数苹果用的数,0, 1, 2, 3, …

整数:自然数 + 负整数,…, -3, -2, -1, 0, 1, 2, 3, …

有理数:所有能写成 p/q(q≠0)的数,包括整数和分数

无理数:无法写成分数的数,小数部分无限不循环

√2 = 1.41421356…(永远不会循环)

π = 3.14159265…

实数:数轴上所有的点,有理数 + 无理数


负数的直觉

为什么需要负数

当”不够减”的时候,负数就登场了

3 - 5 = ? 在自然数里没答案,但现实中这种情况到处都是

三个直觉比喻

温度:零下10度就是 -10°C,零上和零下是正和负

海拔:海平面是 0,死海 -430 米,珠峰 +8848 米

欠债:你有 100 元(+100),借了朋友 200 元(-200),净资产 = -100

数轴

1
2
3
←──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──→
-5 -4 -3 -2 -1 0 1 2 3 4 5
负数 ← │ → 正数

0 是分界线,左边是负数,右边是正数

离 0 越远,绝对值越大


小数的本质

小数就是分数的十进制展开,换了一种写法而已

0.5 = 5/10 = 1/2

0.25 = 25/100 = 1/4

0.1 = 1/10

有限小数 vs 无限小数

有限小数:0.25, 0.375 —— 分母只含因子 2 和 5

无限循环小数:0.333… = 1/3, 0.142857142857… = 1/7

无限不循环小数:√2, π —— 这些就是无理数

为什么 1/3 会变成无限小数

十进制只能精确表示分母是 2 和 5 的组合的分数

3 不是 2 或 5,所以 1/3 在十进制下永远除不尽

这也是计算机用二进制时 0.1 存不精确的根本原因


四则运算的本质

加法:合并

把两堆东西放一起,数一数一共多少

3 + 5 = 8(3个苹果和5个苹果合在一起)

加法的本质是合并和累积

减法:加法的逆 / 求差

“原来有多少,拿走一些,还剩多少”

或者 “两个量相差多少”

8 - 3 = 5(8个苹果拿走3个)

减法就是加上一个负数:8 - 3 = 8 + (-3) = 5

乘法:重复加法 / 面积

3 × 4 = 3 + 3 + 3 + 3 = 12(4个3相加)

也可以理解为面积:长3宽4的矩形面积 = 12

乘法是加法的快捷方式

1
2
3
4
5
6
7
8
9
┌───┬───┬───┬───┐
│ │ │ │ │ ← 3行
├───┼───┼───┼───┤
│ │ │ │ │
├───┼───┼───┼───┤
│ │ │ │ │
└───┴───┴───┴───┘
4列
面积 = 3 × 4 = 12 个格子

除法:乘法的逆 / 分配 / 包含

分配:12块糖分给4个人,每人几块?12 ÷ 4 = 3

包含:12块糖,每人3块,能分几人?12 ÷ 3 = 4

乘法的逆:? × 4 = 12,? = 12 ÷ 4 = 3

除以0没有意义:12块糖分给0个人?这个问题本身不成立


运算律

交换律

加法:a + b = b + a

3 + 5 = 5 + 3 = 8

乘法:a × b = b × a

3 × 4 = 4 × 3 = 12

减法和除法不满足交换律!

5 - 3 = 2,但 3 - 5 = -2

6 ÷ 2 = 3,但 2 ÷ 6 = 1/3

结合律

加法:(a + b) + c = a + (b + c)

(1 + 2) + 3 = 1 + (2 + 3) = 6

乘法:(a × b) × c = a × (b × c)

(2 × 3) × 4 = 2 × (3 × 4) = 24

减法和除法也不满足结合律!

(10 - 3) - 2 = 5,但 10 - (3 - 2) = 9

分配律(最重要的运算律)

a × (b + c) = a × b + a × c

这是心算和代数化简的核心工具

例:3 × (10 + 2) = 3 × 10 + 3 × 2 = 30 + 6 = 36

人话翻译:给每个人都发一份,和先合在一起再发,结果一样

反过来用叫提取公因子:ab + ac = a(b + c)


运算优先级

口诀:先括号,再乘除,后加减

同级运算从左到右

例:2 + 3 × 4 = 2 + 12 = 14(不是 20!)

例:(2 + 3) × 4 = 5 × 4 = 20(括号改变优先级)

嵌套括号从里到外:((2 + 3) × 4 + 1) × 2 = (5 × 4 + 1) × 2 = 21 × 2 = 42

编程中的优先级

编程语言的运算优先级和数学基本一致

但有些不直觉的:2 ** 3 ** 2 在 Python 中是 2 ** (3 ** 2) = 512(右结合)

原则:拿不准就加括号,可读性比炫技重要


心算技巧

凑整法

核心思想:把数凑成整十整百,利用分配律

99 × 37 = (100 - 1) × 37 = 3700 - 37 = 3663

998 × 5 = (1000 - 2) × 5 = 5000 - 10 = 4990

47 + 38 = 47 + (40 - 2) = 87 - 2 = 85

拆分法

把一个数拆成好算的部分

23 × 12 = 23 × 10 + 23 × 2 = 230 + 46 = 276

35 × 16 = 35 × 8 × 2 = 280 × 2 = 560

125 × 8 = 1000(记住这个组合)

补数法

1000 - 637 = ?

技巧:从左到右,每位用 9 减(最后一位用 10 减)

9-6=3, 9-3=6, 10-7=3 → 363

乘法巧算

25 × 任何数 = 先 ÷ 4 再 × 100

25 × 36 = 36/4 × 100 = 9 × 100 = 900

5 × 任何数 = 先 ÷ 2 再 × 10

5 × 68 = 68/2 × 10 = 34 × 10 = 340


开发中的坑

浮点数精度问题

0.1 + 0.2 ≠ 0.3(在几乎所有编程语言中)

原因:0.1 在二进制中是无限循环小数,就像 1/3 在十进制中是 0.333…

IEEE 754 双精度浮点数只有约 15-17 位有效数字

安全隐患:金额计算用浮点数可能导致资损

整数溢出

32位有符号整数范围:-2,147,483,648 ~ 2,147,483,647

超出范围会”翻转”到负数(在 C/Java 中)

Python 的整数没有上限(大整数自动扩展),但性能会下降

安全隐患:整数溢出是经典的安全漏洞类型

除法取整方向

Python: -7 // 2 = -4(向下取整)

Java/C: -7 / 2 = -3(向零取整)

写分页逻辑或者时间戳计算时要注意这个差异


Python 代码实战

浮点精度问题演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 经典的浮点精度问题
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False !!!

# 查看 0.1 在内存中的真实值
from decimal import Decimal
print(Decimal(0.1))
# 0.1000000000000000055511151231257827021181583404541015625

# 正确的浮点比较方式
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True

# 或者用一个容差值
epsilon = 1e-9
print(abs((0.1 + 0.2) - 0.3) < epsilon) # True

用 Decimal 做精确计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from decimal import Decimal, getcontext

# 设置精度
getcontext().prec = 50

# 用字符串初始化(不要用浮点数!)
a = Decimal('0.1')
b = Decimal('0.2')
c = Decimal('0.3')

print(a + b == c) # True !!!
print(a + b) # 0.3

# 金额计算示例
price = Decimal('19.99')
quantity = Decimal('3')
tax_rate = Decimal('0.13')

subtotal = price * quantity
tax = subtotal * tax_rate
total = subtotal + tax

print(f"小计: {subtotal}") # 59.97
print(f"税额: {tax}") # 7.7961
print(f"总计: {total}") # 67.7661
# 四舍五入到分
print(f"总计(四舍五入): {total.quantize(Decimal('0.01'))}") # 67.77

整数运算与大整数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Python 整数没有上限
big = 2 ** 1000
print(f"2^1000 有 {len(str(big))} 位数字") # 302 位

# 整除和取余
print(17 // 5) # 3 (整除/地板除)
print(17 % 5) # 2 (取余)
print(divmod(17, 5)) # (3, 2) 同时得到商和余数

# 注意负数的行为
print(-7 // 2) # -4 (向下取整,不是向零取整)
print(-7 % 2) # 1 (余数始终非负)

# 运算律验证
a, b, c = 7, 3, 5
# 分配律
assert a * (b + c) == a * b + a * c
# 交换律
assert a + b == b + a
assert a * b == b * a
# 结合律
assert (a + b) + c == a + (b + c)
print("所有运算律验证通过")

心算技巧的代码验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 凑整法验证
print(99 * 37) # 3663
print(100 * 37 - 1 * 37) # 3663 ← 凑整法

# 拆分法验证
print(23 * 12) # 276
print(23 * 10 + 23 * 2) # 276 ← 拆分法

# 补数法验证
print(1000 - 637) # 363

# 25 × n 的技巧验证
n = 36
print(25 * n) # 900
print(n // 4 * 100) # 900 ← 技巧

# 写一个心算辅助函数
def mental_multiply(a, b):
"""展示心算拆分过程"""
# 把 b 拆成 十位 × 10 + 个位
b_tens = (b // 10) * 10
b_ones = b % 10
part1 = a * b_tens
part2 = a * b_ones
print(f"{a} × {b}")
print(f"= {a} × {b_tens} + {a} × {b_ones}")
print(f"= {part1} + {part2}")
print(f"= {part1 + part2}")
return part1 + part2

mental_multiply(23, 17)

实际应用场景

安全领域

密码学基础运算:模加、模乘(RSA 算法的核心)

哈希碰撞概率计算涉及大量算术

密码强度:8位数字密码有 10^8 = 1亿种可能,暴力破解只需几秒

大数据领域

SQL 中的 SUM/AVG/COUNT 就是加法和除法

数据分页:OFFSET 和 LIMIT 的计算

MapReduce 的 Reduce 阶段就是各种聚合运算

后端开发

金额计算必须用整数(单位:分)或 Decimal,绝不用浮点

分布式 ID 生成(雪花算法)涉及位运算

负载均衡的权重计算


常见误区

误区1:0.1 + 0.2 = 0.3

真相:在浮点数运算中不等于,见上方代码

误区2:负数的负数是正数,所以 -(-3) = 3

这个是对的,但很多人在连续负号时搞混

误区3:乘法一定让数变大

乘以小于1的正数会变小:5 × 0.5 = 2.5

乘以负数会变号:5 × (-2) = -10

误区4:除以一个数等于乘以它的小数

对的,但容易搞反:÷2 = ×0.5,÷0.5 = ×2

误区5:先乘除后加减总是记得,但遇到负号就忘了

-3^2 = -(3^2) = -9,不是 (-3)^2 = 9


练习题

题目1:心算

不用计算器,算出 99 × 45

提示:用凑整法

答案:(100-1) × 45 = 4500 - 45 = 4455

题目2:运算律应用

用分配律快速计算 37 × 101

答案:37 × (100 + 1) = 3700 + 37 = 3737

题目3:浮点陷阱

写一段 Python 代码,验证 0.1 + 0.1 + 0.1 是否等于 0.3

用两种方式修正这个问题

题目4:实际场景

电商系统中,商品价格 19.99 元,用户买了 3 件,加上 13% 增值税

用 Python 的 Decimal 模块计算最终金额(精确到分)

题目5:负数运算

计算:(-3) × (-5) + (-2) × 4 - (-6) ÷ 3

逐步写出过程

答案:15 + (-8) - (-2) = 15 - 8 + 2 = 9


小结

数的分类:自然数 ⊂ 整数 ⊂ 有理数 ⊂ 实数

四则运算的本质:加(合并)、减(加的逆)、乘(重复加)、除(乘的逆)

三大运算律:交换律、结合律、分配律(分配律最重要)

开发关键点:浮点精度用 Decimal,金额用整数(分),注意除法取整方向

下一节:01-分数与小数


上一章 目录 下一章
数学重学路线图 01-分数与小数