Day 004 — 数字与运算:图解
一图胜千言:用视觉方式理解数字的底层原理。
1. IEEE 754 双精度浮点数的内存布局
64-bit 双精度浮点数布局
符号位 (1 bit) 指数位 (11 bits) 尾数/有效位 (52 bits)
↓ ↓ ↓
┌────┬────────────────┬────────────────────────────────────────────────────────────────────┐
│ 0 │ 01111111111 │ 1001001000011111101101010100010001000010110100011000 │
└────┴────────────────┴────────────────────────────────────────────────────────────────────┘
(-1)^0 2^(1023-1023)=2^0 1 + (二进制小数)
= +1 = 1 = 1.5707963267948966...
公式: value = (-1)^s × 2^(e-1023) × (1 + f/2^52)
示例: 数值 π ≈ 3.141592653589793
位模式: 0 10000000000 1001001000011111101101010100010001000010110100011000
解析:
s = 0 → 正数
e = 1024 → 指数 = 1024 - 1023 = 1
f = 0x921FB54442D18 → 尾数部分
value = 1 × 2^1 × 1.5707963267948966...
= 3.141592653589793...
特殊值编码
指数位全 0 → 非规格化数(非常接近 0 的数值)
0 00000000000 0000000000000000000000000000000000000000000000000000 = +0
1 00000000000 0000000000000000000000000000000000000000000000000000 = -0
指数位全 1 + 尾数全 0 → 无穷大
0 11111111111 0000000000000000000000000000000000000000000000000000 = +inf
1 11111111111 0000000000000000000000000000000000000000000000000000 = -inf
指数位全 1 + 尾数非 0 → NaN
0 11111111111 1000000000000000000000000000000000000000000000000000 = NaN
2. 二进制分数:为什么 0.1 不精确
0.1 的二进制表示是无限循环小数:
0.1 × 2 = 0.2 → 取整数 0
0.2 × 2 = 0.4 → 取整数 0
0.4 × 2 = 0.8 → 取整数 0
0.8 × 2 = 1.6 → 取整数 1 ← 余 0.6
0.6 × 2 = 1.2 → 取整数 1 ← 余 0.2 (回到第二步!)
0.2 × 2 = 0.4 → 取整数 0
...
0.1 (十进制) = 0.00011001100110011... (二进制,无限循环)
↑ ↑ ↑ 循环节 1100
────
而 0.5 精确:
0.5 × 2 = 1.0 → 取整数 1
0.5 (十进制) = 0.1 (二进制) ← 精确!
规则:分母只含 2 的质因数才精确
1/2 = 0.5 ✓ (分母=2)
1/4 = 0.25 ✓ (分母=4=2²)
1/8 = 0.125 ✓ (分母=8=2³)
1/10 = 0.1 ✗ (分母=10=2×5)
1/3 = 0.333... ✗ (分母=3)
3. 运算符优先级层次结构
高优先级
│
┌────┴────┐
│ (...) │ ← 括号永远最高
└────┬────┘
│
┌────┴────┐
│ ** │ ← 幂运算(右结合)
└────┬────┘
│
┌────┴────┐
│ +x -x ~x│ ← 一元运算符
└────┬────┘
│
┌────┴────┐
│ */ // % │ ← 乘除法
└────┬────┘
│
┌────┴────┐
│ + - │ ← 加减法
└────┬────┘
│
┌────┴────┐
│ << >> │ ← 位移位
└────┬────┘
│
┌────┴────┐
│ & │ ← 位与
└────┬────┘
│
┌────┴────┐
│ ^ │ ← 位异或
└────┬────┘
│
┌────┴────┐
│ | │ ← 位或
└────┬────┘
│
┌────┴────┐
│ == != │ ← 比较运算符
│ < > <= │
│ is in │
└────┬────┘
│
┌────┴────┐
│ not │ ← 逻辑非
└────┬────┘
│
┌────┴────┐
│ and │ ← 逻辑与
└────┬────┘
│
┌────┴────┐
│ or │ ← 逻辑或
└────┬────┘
│
┌────┴────┐
│if-else │ ← 三元表达式(右结合)
└────┬────┘
│
┌────┴────┐
│ := │ ← 海象运算符(右结合)
└─────────┘
│
低优先级
4. 位运算真值表与图解
基本位运算真值表
输入 A: 0 0 1 1
输入 B: 0 1 0 1
───────────────
A & B: 0 0 0 1 (AND:全 1 才 1)
A | B: 0 1 1 1 (OR:有 1 就 1)
A ^ B: 0 1 1 0 (XOR:不同才 1)
~A: 1 1 0 0 (NOT:取反)
位运算图解示例
例:mask = 0b1101, value = 0b1010
┌───────┐
│ value │ 1 0 1 0
└───┬───┘
│
┌────┴────┐
│ AND & │── 1 0 0 0 → 保留特定位
└────┬────┘
│
┌───┴───┐
│ mask │ 1 1 0 1
└───────┘
┌───────┐
│ value │ 1 0 1 0
└───┬───┘
│
┌────┴────┐
│ OR | │── 1 1 1 1 → 将特定位设为 1
└────┬────┘
│
┌───┴───┐
│ mask │ 1 1 0 1
└───────┘
┌───────┐
│ value │ 1 0 1 0
└───┬───┘
│
┌────┴────┐
│ XOR ^ │── 0 1 1 1 → 翻转特定位
└────┬────┘
│
┌───┴───┐
│ mask │ 1 1 0 1
└───────┘
位运算实战技巧图解
检查奇偶性 (n & 1):
n = 5 = 0b101
n & 1 = 0b101 & 0b001 = 1 → 奇数 ✓
2 的幂检测 (n & (n-1)):
8 = 1000 16 = 10000
7 = 0111 15 = 01111
& = 0000 ✓ & = 00000 ✓ (2 的幂)
6 = 0110 9 = 01001
5 = 0101 8 = 01000
& = 0100 ✗ & = 01000 ✗ (不是 2 的幂)
取最低位的 1 (n & -n):
n = 108 = 01101100
-n = -108 = 10010100 (补码)
& = 4 = 00000100 ✓ (最低位 1 的值)
5. 类型转换链
隐式类型转换方向(自动提升精度):
int ──────→ float ──────→ complex
(bool) ↗
显式类型转换:
┌────────────┐
│ int(x) │ ← 浮点数: 截断取整
│ │ ← 字符串: 解析整数
│ │ ← bool: True→1, False→0
└────────────┘
┌────────────┐
│ float(x) │ ← 整数/字符串
└────────────┘
┌────────────┐
│ complex(r) │ ← 实部,虚部为 0
│ complex(r,i)│ ← 实部 + 虚部
└────────────┘
┌────────────┐
│ bool(x) │ ← 0 / 空 / None → False
│ │ ← 其他 → True
└────────────┘
数值 → 字符串:
str(42) → "42"
repr(3.14) → "3.14"
bin(42) → "0b101010"
oct(42) → "0o52"
hex(42) → "0x2a"
f"{42:08b}" → "00101010" (格式化: 8位二进制, 补零)
6. 小整数缓存机制
CPython 启动时预创建的整数对象池:
┌────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ -5 │ -4 │ -3 │ -2 │ -1 │ 0 │ 1 │ 2 │ 3 │ ...
└────┴────┴────┴────┴────┴────┴────┴────┴────┘
⋮
┌────┬────┬────┬────┬────┬────┬────┬────┬────┐
│250 │251 │252 │253 │254 │255 │256 │ │ │
└────┴────┴────┴────┴────┴────┴────┴────┴────┘
- 范围: [-5, 256] 预分配
- 在此范围内, a is b 总是 True
- 超出此范围, a is b 可能 False
- 这只是 CPython 的实现细节,不是语言规范