- Published on
2.2.进制
- Authors

- Name
- xiaobai
1.进制的概念
核心思想:进制是一种计数和表示数字的方式,它规定了"逢几进一"。
我们最熟悉的是十进制,但在计算机世界里,二进制、八进制和十六进制扮演着至关重要的角色。
1.1.十进制
- 基数:10
- 数码:0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- 规则:逢十进一
- 示例:数字
123实际上是1 * 10² + 2 * 10¹ + 3 * 10⁰
1.2.二进制
- 基数:2
- 数码:0, 1
- 规则:逢二进一
- 重要性:这是计算机硬件(CPU、内存)直接理解和处理的数据形式。所有数据在底层都是一串 0 和 1。
- 示例:二进制数
1011表示为:1 * 2³ + 0 * 2² + 1 * 2¹ + 1 * 2⁰ = 8 + 0 + 2 + 1 = 11(十进制)
1.3.八进制
- 基数:8
- 数码:0, 1, 2, 3, 4, 5, 6, 7
- 规则:逢八进一
- 特点:曾经在 Unix 系统权限管理中广泛使用,现在较少见。
- 示例:八进制数
17表示为:1 * 8¹ + 7 * 8⁰ = 8 + 7 = 15(十进制)
1.4.十六进制
- 基数:16
- 数码:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F (其中 A=10, B=11, ..., F=15)
- 规则:逢十六进一
- 重要性:极其常用。因为它与二进制有完美的对应关系(1位十六进制数对应4位二进制数),非常适合用来简化冗长的二进制表示,常用于表示内存地址、颜色值等。
- 示例:十六进制数
1F表示为:1 * 16¹ + 15 * 16⁰ = 16 + 15 = 31(十进制)
2.Python 中的进制操作
Python 提供了非常方便的内置函数来处理不同进制的数字。
2.1.表示不同进制的字面量
在代码中,你可以直接用特定前缀来表示不同进制的数字。
# 十进制 (Decimal) - 默认,无前缀)
dec_num = 100
print(dec_num) # 输出: 100
# 二进制 (Binary) - 前缀 `0b` 或 `0B`
bin_num = 0b1100100 # 这就是十进制的 100
print(bin_num) # 输出: 100 (Python会自动以十进制形式打印)
# 八进制 (Octal) - 前缀 `0o` 或 `0O`
oct_num = 0o144 # 这就是十进制的 100
print(oct_num) # 输出: 100
# 十六进制 (Hexadecimal) - 前缀 `0x` 或 `0X`
hex_num = 0x64 # 这就是十进制的 100
print(hex_num) # 输出: 100
2.2.进制转换函数
Python 有三个核心函数用于将十进制整数转换为其他进制的字符串。
bin(i)-> 二进制字符串oct(i)-> 八进制字符串hex(i)-> 十六进制字符串
num = 255
# 转换为不同进制的字符串
bin_str = bin(num)
oct_str = oct(num)
hex_str = hex(num)
print(f"十进制 {num}:")
print(f"二进制 {bin_str}") # 输出: 0b11111111
print(f"八进制 {oct_str}") # 输出: 0o377
print(f"十六进制 {hex_str}") # 输出: 0xff
注意:这些函数返回的是字符串,并且带有前缀。
2.3.将字符串转换为十进制整数
这是最强大的一个功能,使用 int() 函数。
int() 函数可以接受两个参数:
- 第一个参数:要转换的字符串
- 第二个参数
base:这个字符串所表示的数的进制(2-36)
# 将二进制字符串(不带前缀也可)转换为十进制
binary_string = "11111111"
# binary_string = "0b11111111" # 带前缀也可以
decimal_from_bin = int(binary_string, 2)
print(f"二进制 {binary_string} 是十进制 {decimal_from_bin}") # 输出: 255
# 将八进制字符串转换为十进制
octal_string = "377"
decimal_from_oct = int(octal_string, 8)
print(f"八进制 {octal_string} 是十进制 {decimal_from_oct}") # 输出: 255
# 将十六进制字符串转换为十进制
hex_string = "ff" # 大小写均可
# hex_string = "0xFF" # 带前缀也可以
decimal_from_hex = int(hex_string, 16)
print(f"十六进制 {hex_string} 是十进制 {decimal_from_hex}") # 输出: 255
# 甚至可以转换自定义进制的字符串,比如三进制
ternary_string = "100110"
decimal_from_ternary = int(ternary_string, 3)
print(f"三进制 {ternary_string} 是十进制 {decimal_from_ternary}") # 输出: 255 (1*3^5 + 1*3^2 + 1*3^1 = 255)
3.综合示例与应用场景
3.1.处理颜色值(RGB)
网页和图形编程中,颜色常用十六进制表示。
# 一个红色值
red_hex = "#FF0000"
# 提取出RGB分量并转换为十进制
red_component = int(red_hex[1:3], 16) # 取 ‘FF’, 以16进制解析
green_component = int(red_hex[3:5], 16) # 取 ‘00’
blue_component = int(red_hex[5:7], 16) # 取 ‘00’
print(f"颜色 {red_hex} 的RGB分量为:")
print(f" R: {red_component}")
print(f" G: {green_component}")
print(f" B: {blue_component}")
# 输出:
# R: 255
# G: 0
# B: 0
3.2.格式化输出(去掉前缀)
有时我们不需要 0b, 0x 这样的前缀。
num = 42
# 方法1:使用字符串切片
hex_with_prefix = hex(num) # 0x2a
hex_without_prefix_1 = hex_with_prefix[2:] # 从第2个字符开始截取 2a
print(hex_without_prefix_1)#2a
# 方法2:使用格式化字符串 (f-string) - 更推荐!
# 格式: `:x` 表示十六进制, `:b` 表示二进制, `:o` 表示八进制
hex_without_prefix_2 = f"{num:x}" # 小写
hex_without_prefix_3 = f"{num:X}" # 大写
bin_without_prefix = f"{num:b}"
print(hex_without_prefix_2) # 输出: 2a
print(hex_without_prefix_3) # 输出: 2A
print(bin_without_prefix) # 输出: 101010
4.总结
| 进制 | 规则 | Python 前缀 | 转换函数 | 应用场景 |
|---|---|---|---|---|
| 十进制 | 逢十进一 | 无 | int("123") | 人类日常计算 |
| 二进制 | 逢二进一 | 0b | bin() | 计算机底层逻辑、位运算 |
| 八进制 | 逢八进一 | 0o | oct() | 历史遗留(如Linux文件权限) |
| 十六进制 | 逢十六进一 | 0x | hex() | 内存地址、颜色代码、数据包 |
核心要点:
- 在计算机内存中,所有数据最终都是二进制。
- Python 中,带前缀的数字(如
0xff)在解释时会被直接转换为十进制整数对象。 bin(),oct(),hex()用于将数字变成字符串。int(str, base)用于将字符串解析为数字,是逆向转换的万能钥匙。- 熟练使用
f-string的格式化功能可以方便地控制输出格式。
5.以下内容不用看,Python全部学完后再看
6.比特、字节与存储单位
6.1.核心概念:比特与字节
6.1.1.1. 比特(Bit)
- 英文:Bit (Binary Digit)
- 含义:计算机中最小的数据单位,代表一个二进制位
- 数值:只能是 0 或 1
- 类比:可以把它想象成一个开关,要么开(1),要么关(0)
- 重要性:所有数据在计算机底层都是以比特流(一串0和1)的形式存储和处理的
# 一个数字在内存中的比特表示
num = 65
binary = bin(num) # 0b1000001
print(f"数字 {num} 的二进制表示:{binary}")
print(f"占用 {len(binary) - 2} 个比特位") # 减去 '0b' 前缀
6.1.2.2. 字节(Byte)
- 英文:Byte
- 含义:计算机中最基本的内存寻址单位和数据计量单位
- 换算:1 字节 = 8 比特(1 Byte = 8 bits)
- 重要性:一个字节可以表示一个字符(比如英文字母、数字、标点)。早期的编码系统(如 ASCII)就是用 1 个字节(8 位)来定义一个字符的
- 表示范围:1 个字节可以表示 (2^8 = 256) 个不同的值(0-255)
# 字符与字节
char = 'A'
print(f"字符 '{char}' 的 ASCII 码:{ord(char)}") # 65
print(f"二进制表示:{bin(ord(char))}") # 0b1000001
print(f"占用:1 个字节(8 个比特)")
# 字符串的字节长度
text = "Hello"
bytes_data = text.encode('utf-8')
print(f"\n字符串 '{text}' 占用 {len(bytes_data)} 个字节")
# 查看每个字节
print("每个字节的值:", [byte for byte in bytes_data])
# [72, 101, 108, 108, 111] - 对应 H e l l o 的 ASCII 码
6.2.存储单位:二进制前缀
由于计算机使用二进制,其单位换算通常是 1024 ((2^10)) 倍,而不是国际单位制(SI)的 1000 倍。为了区分,有专门的二进制前缀。
| 单位名称 | 缩写 | 换算关系 | 字节数 | 示例与应用 |
|---|---|---|---|---|
| 字节 | B | 基础单位 | 1 | 一个英文字符 |
| 千字节 | KiB | 1 KiB = 1024 B | 1,024 | 一小段文本、小图标 |
| 兆字节 | MiB | 1 MiB = 1024 KiB | 1,048,576 | 一首 MP3 歌曲、高清照片 |
| 吉字节 | GiB | 1 GiB = 1024 MiB | 1,073,741,824 | 高清电影、大型软件 |
| 太字节 | TiB | 1 TiB = 1024 GiB | 1,099,511,627,776 | 个人电脑硬盘、大型数据库 |
| 拍字节 | PiB | 1 PiB = 1024 TiB | (2^50) | 大型数据中心 |
| 艾字节 | EiB | 1 EiB = 1024 PiB | (2^60) | 全球互联网流量 |
注意:在很多非正式的场合,人们仍然习惯使用 KB, MB, GB 来表示 1024 的倍数,但从技术标准上讲,KiB, MiB, GiB 才是准确的。
6.3.网络与速度单位:十进制前缀
在网络和通信领域,通常使用标准的国际单位制(SI)前缀,即 1000 倍率。
| 单位名称 | 缩写 | 换算关系 | 应用场景 |
|---|---|---|---|
| 比特每秒 | bps (b/s) | 基础单位 | 网络带宽、传输速率 |
| 千比特每秒 | Kbps (Kb/s) | 1 Kbps = 1,000 bps | 旧的拨号网络 |
| 兆比特每秒 | Mbps (Mb/s) | 1 Mbps = 1,000 Kbps | 现代家庭宽带、Wi-Fi |
| 吉比特每秒 | Gbps (Gb/s) | 1 Gbps = 1,000 Mbps | 高速光纤、数据中心 |
| 太比特每秒 | Tbps (Tb/s) | 1 Tbps = 1,000 Gbps | 国家级骨干网络 |
6.3.1.重要区别:Byte vs. bit
这是最容易混淆的地方!
- Byte (B,大写):字节,用于表示存储容量(文件大小、硬盘容量、内存大小)
- bit (b,小写):比特,用于表示传输速度(网络带宽、下载速度)
换算:1 Byte = 8 bits
6.3.2.实际应用举例
你的家庭宽带是 100 Mbps(100 兆比特每秒)。那么理论最大下载速度是多少 MB/s(兆字节每秒)?
100 Mbps = 100,000,000 bits per second
100,000,000 bps ÷ 8 = 12,500,000 Bps ≈ 12.5 MB/s
所以,当你用下载工具时,显示的最高速度大概在 12.5 MB/s 左右。
6.4.Python 中的单位处理
Python 本身不内置单位转换,但我们可以轻松编写函数来计算。
6.4.1.格式化文件大小
这个函数可以将字节数转换成人类易读的格式(使用二进制前缀)。
def format_file_size(size_in_bytes):
"""
将字节数格式化为人类可读的字符串 (使用二进制前缀 KiB, MiB 等)
参数:
size_in_bytes: 文件大小(字节)
返回:
格式化后的字符串
"""
# 定义单位阶梯
units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']
size = float(size_in_bytes)
index = 0
# 循环除以1024,直到找到合适的单位
while size >= 1024 and index < len(units) - 1:
size /= 1024.0
index += 1
# 格式化输出,保留2位小数
return f"{size:.2f} {units[index]}"
# 测试不同大小的文件
file_sizes = [
500, # 500 字节
1536, # 1.5 KiB
1048576, # 1 MiB
3221225472, # 3 GiB
1099511627776 # 1 TiB
]
print("文件大小转换示例:")
for size in file_sizes:
print(f"{size:>15} 字节 = {format_file_size(size)}")
# 输出:
# 500 字节 = 500.00 B
# 1536 字节 = 1.50 KiB
# 1048576 字节 = 1.00 MiB
# 3221225472 字节 = 3.00 GiB
# 1099511627776 字节 = 1.00 TiB
6.4.2.网络速度换算
def mbps_to_mb_per_second(mbps_speed):
"""
将网络速度从 Mbps (兆比特/秒) 转换为 MB/s (兆字节/秒)
参数:
mbps_speed: 网络带宽(Mbps)
返回:
下载速度(MB/s)
"""
mb_per_second = mbps_speed / 8.0
return mb_per_second
# 测试不同的宽带速度
bandwidths = [50, 100, 300, 500, 1000] # 常见的宽带速度
print("\n网络带宽与下载速度对照表:")
print("-" * 50)
print(f"{'带宽':<10} {'理论最大下载速度':<20}")
print("-" * 50)
for bw in bandwidths:
download_speed = mbps_to_mb_per_second(bw)
print(f"{bw:>6} Mbps -> {download_speed:>8.2f} MB/s")
# 输出:
# 网络带宽与下载速度对照表:
# --------------------------------------------------
# 带宽 理论最大下载速度
# --------------------------------------------------
# 50 Mbps -> 6.25 MB/s
# 100 Mbps -> 12.50 MB/s
# 300 Mbps -> 37.50 MB/s
# 500 Mbps -> 62.50 MB/s
# 1000 Mbps -> 125.00 MB/s
6.4.3.下载时间计算
def calculate_download_time(file_size_mb, bandwidth_mbps):
"""
计算文件下载所需时间
参数:
file_size_mb: 文件大小(MB)
bandwidth_mbps: 网络带宽(Mbps)
返回:
下载时间(秒)
"""
# 将文件大小转换为 Mb (兆比特)
file_size_mb_bits = file_size_mb * 8
# 计算时间(秒)
time_seconds = file_size_mb_bits / bandwidth_mbps
return time_seconds
# 测试:下载一个 2GB 的电影
file_size = 2 * 1024 # 2048 MB
bandwidths = [50, 100, 300, 1000]
print("\n下载 2GB 电影所需时间:")
print("-" * 50)
for bw in bandwidths:
time_sec = calculate_download_time(file_size, bw)
time_min = time_sec / 60
if time_min < 1:
print(f"{bw:>4} Mbps: {time_sec:.1f} 秒")
else:
print(f"{bw:>4} Mbps: {time_min:.1f} 分钟 ({time_sec:.0f} 秒)")
# 输出示例:
# 50 Mbps: 5.5 分钟 (327 秒)
# 100 Mbps: 2.7 分钟 (164 秒)
# 300 Mbps: 54.6 秒
# 1000 Mbps: 16.4 秒
6.4.4.比特操作
# 查看一个数字的比特表示
def show_bits(number, byte_count=1):
"""显示数字的比特表示"""
# 转换为二进制字符串(去掉 0b 前缀)
binary = bin(number)[2:]
# 填充到指定字节数
total_bits = byte_count * 8
binary = binary.zfill(total_bits)
# 格式化输出(每8位一组)
formatted = ' '.join([binary[i:i+8] for i in range(0, len(binary), 8)])
print(f"数字 {number} 的比特表示:")
print(f" 二进制: {formatted}")
print(f" 占用: {byte_count} 字节 ({total_bits} 比特)")
# 测试
show_bits(65, 1) # 字符 'A'
print()
show_bits(255, 1) # 最大的单字节数
print()
show_bits(1024, 2) # 需要2个字节
# 输出:
# 数字 65 的比特表示:
# 二进制: 01000001
# 占用: 1 字节 (8 比特)
#
# 数字 255 的比特表示:
# 二进制: 11111111
# 占用: 1 字节 (8 比特)
#
# 数字 1024 的比特表示:
# 二进制: 00000100 00000000
# 占用: 2 字节 (16 比特)
6.5.常见误区与注意事项
| 概念 | 单位 | 关键点 | 常见误区 |
|---|---|---|---|
| 最小单位 | 比特 (bit, b) | 0 或 1 | 与字节混淆 |
| 基本单位 | 字节 (Byte, B) | 1 Byte = 8 bits | 忘记大小写区别:B ≠ b |
| 存储容量 | KiB, MiB, GiB | 以 1024 为进制 | 硬盘厂商用 1000 进制,所以标称 1TB 的硬盘在系统里显示约 931GiB |
| 网络速度 | Mbps, Gbps | 以 1000 为进制,单位是 bit | 误将 100 Mbps 宽带认为是 100 MB/s 的下载速度(实际约 12.5 MB/s) |
6.5.1.1. 硬盘容量的"缩水"现象
# 为什么 1TB 硬盘实际只有 931GB?
advertised_tb = 1 # 厂商标称 1TB
advertised_bytes = advertised_tb * 1000 * 1000 * 1000 * 1000 # 厂商用1000进制
# 转换为系统显示的容量(1024进制)
actual_gib = advertised_bytes / (1024 ** 3)
print(f"厂商标称: {advertised_tb} TB")
print(f"实际容量: {advertised_bytes:,} 字节")
print(f"系统显示: {actual_gib:.2f} GiB")
# 输出:
# 厂商标称: 1 TB
# 实际容量: 1,000,000,000,000 字节
# 系统显示: 931.32 GiB
6.5.2.2. 大小写的重要性
# 小心大小写!
print("Byte (B,大写) = 字节,用于存储容量")
print("bit (b,小写) = 比特,用于传输速度")
print()
print("100 MB = 100 兆字节 = 800 兆比特 = 800 Mb")
print("100 Mb = 100 兆比特 = 12.5 兆字节 = 12.5 MB")
6.6.核心记忆点
- B 和 b 差 8 倍
- 1 Byte (B) = 8 bits (b)
- 大写 B = 字节,小写 b = 比特
- 存储容量使用 Byte
- 文件大小、硬盘容量、内存大小
- 单位:B, KiB, MiB, GiB, TiB
- 进制:1024
- 网络速度使用 bit
- 网络带宽、下载速度
- 单位:bps, Kbps, Mbps, Gbps
- 进制:1000
- 速度换算公式
- 下载速度 (MB/s) = 带宽 (Mbps) ÷ 8
- 100 Mbps 宽带 ≈ 12.5 MB/s 下载速度
- 硬盘容量"缩水"
- 厂商用 1000 进制(1TB = 1000GB)
- 系统用 1024 进制(1TiB = 1024GiB)
- 1TB ≈ 931GiB
6.7.实用小工具
class StorageConverter:
"""存储单位转换工具类"""
@staticmethod
def bytes_to_human(bytes_count, binary=True):
"""将字节转换为人类可读格式"""
if binary:
units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB']
base = 1024
else:
units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
base = 1000
size = float(bytes_count)
for unit in units[:-1]:
if abs(size) < base:
return f"{size:.2f} {unit}"
size /= base
return f"{size:.2f} {units[-1]}"
@staticmethod
def mbps_to_mbytes(mbps):
"""将 Mbps 转换为 MB/s"""
return mbps / 8
@staticmethod
def mbytes_to_mbps(mbytes):
"""将 MB/s 转换为 Mbps"""
return mbytes * 8
# 使用示例
converter = StorageConverter()
# 转换文件大小
print(converter.bytes_to_human(1536000000)) # 1.43 GiB
print(converter.bytes_to_human(1536000000, binary=False)) # 1.54 GB
# 转换网速
print(f"100 Mbps = {converter.mbps_to_mbytes(100):.2f} MB/s")
print(f"12.5 MB/s = {converter.mbytes_to_mbps(12.5):.0f} Mbps")

