第二课:数据表示与计算
一、进制——计算机的数学基石
1.1、人类计数方法的演进历程
1.1.1 手指计数:十进制的生物学起源
核心原理:人类双手共10根手指 → 最自然的计数工具
考古证据:
- 古埃及象形数字:𓏤(1)、𓎆(10)、𓍢(100) → 10倍递增
- 汉语数字:"十"字即双手交叉象形
- 拉丁语数字:digit(手指/数字)同源
数学表达:
( 取值 0-9)
1.1.2. 其他进制的历史实践
| 进制 | 文明 | 应用场景 | 现代遗存 |
|---|---|---|---|
| 5进制 | 玛雅/凯尔特 | 单手计数 | 罗马数字Ⅴ=5 |
| 12进制 | 苏美尔 | 天文历法(12月/12时辰) | 时钟/打(12个) |
| 20进制 | 玛雅/阿兹特克 | 手脚并用(20指趾) | 法语80=4×20(quatre-vingts) |
| 60进制 | 巴比伦 | 角度/时间(60秒/分) | 全球时间系统 |
1.1.3. 位值制革命:印度-阿拉伯数字
关键突破:
- 数字位置决定其权重(如 123 中 1 表示 100)
- 引入 0 作为占位符(公元628年 婆罗摩笈多)
罗马数字:CXXIII = 123 → 无位值概念
阿拉伯数字:123 = 1×100 + 2×10 + 3×1 → 位值制
1.2 计算机选择二进制的必然性
1.2.1 电子电路的物理本质
技术实现对比:
| 进制 | 状态数量 | 电路稳定性 | 误差容限 | 实现成本 |
|---|---|---|---|---|
| 二进制 | 2 | ★★★★★ | 极高 | 极低 |
| 十进制 | 10 | ★☆☆☆☆ | 极低 | 极高 |
| 三进制 | 3 | ★★☆☆☆ | 中等 | 高 |
关键实验:
1940年代贝尔实验室尝试十进制计算机
→ 需要10种稳定电压状态(0.5V,1.5V,...,4.5V)
→ 电压波动±0.2V即导致"3"和"4"混淆
→ 项目失败
1.2.2 布尔代数的完美契合
1854年乔治·布尔提出逻辑代数:
(与) → 串联开关
(或) → 并联开关
(非) → 反向器
电路实现:
二进制加法器:
A ⊕ B = (¬A∧B)∨(A∧¬B) → 异或门
进位 = A∧B → 与门
1.3 历史交汇点:从人脑到电脑
1.3.1 莱布尼茨的东方启示
1703年莱布尼茨发表《二进制算术阐释》:
- 受《易经》阴阳思想启发(0=阴,1=阳)
- "这是最完美的逻辑系统,一切数可归结为0和1"
历史启示:
人类选择十进制是生物进化的偶然结果
计算机选择二进制是物理规律的必然选择
这种差异恰恰体现了人类智慧——创造与自然规律协作的工具>
二、进制转换
2.1 十进制与其它进制互转的三种核心方法
2.1.1 除基取余法(十进制→其他进制)
数学原理:
整数可表示为多项式:
根据多项式的定义,将整数转换成 b 进制时,将整数除以2,并记录商和余数,余数即为 。
- 每次除法实质是分离当前最低位
- 逆序操作重建了数字的位权结构
- 类似不断剥离数字的"外壳"
- 这个可以列数学多项式推导
// 整数转换C++实现
string intToBase(int n, int base) {
if (n == 0) return "0";
string digits = "0123456789ABCDEF";
string result = "";
while (n > 0) {
result = digits[n % base] + result; // 余数逆序添加
n /= base;
}
return result;
}
示例: 将 13 转换为二进制
结果: 10101101₂ (从下往上读余数)
2.1.2 乘基取整法(十进制小数→其他进制)
小数可表示为多项式:
转换过程:
- 乘以基数 得到整数和小数部分:
- 整数 即是小数点后第一位
- 对小数部分 重复上述过程:
- 直到小数部分为0或达到精度,整数序列 即为结果
示例: 将 0.6875 转换为二进制
0.6875 × 2 = 1.375 → 取 1,余 0.375
0.375 × 2 = 0.75 → 取 0,余 0.75
0.75 × 2 = 1.5 → 取 1,余 0.5
0.5 × 2 = 1.0 → 取 1,余 0.0
结果: 0.1011₂ (从上往下读整数) `
* 小数精度控制` 问题: 0.3₁₀ 转二进制时无限循环
0.3×2=0.6 → 0
0.6×2=1.2 → 1
0.2×2=0.4 → 0
0.4×2=0.8 → 0
0.8×2=1.6 → 1 (开始循环)
解决方案: 指定精度(如保留8位) 结果:0.01001100₂(近似值)
string fracToBase(double f, int base, int precision) {
string digits = "0123456789ABCDEF";
string result = ".";
for (int i = 0; i < precision && f > 0; i++) {
f *= base;
int digit = (int)f; // 取整数部分
result += digits[digit];
f -= digit; // 保留小数部分
}
return result;
}
2.1.3 位权展开法(其他进制→十进制)
公式:
示例: 将 3A.2C₁₆ 转换为十进制
3A.2C₁₆ = 3×16¹ + 10×16⁰ + 2×16⁻¹ + 12×16⁻²
= 3×16 + 10×1 + 2/16 + 12/256
= 48 + 10 + 0.125 + 0.046875
= 58.171875₁₀