深入理解计算机进制:从原理到 C++ 实现

目录

前言

一、各进制的核心作用

1. 二进制(Binary, Base-2)

2. 八进制(Octal, Base-8)

3. 十进制(Decimal, Base-10)

4. 十六进制(Hexadecimal, Base-16)

二、进制转换的数学原理

1、十进制 ↔ 二进制转换

1. 十进制 → 二进制

2. 二进制 → 十进制

2、十进制 ↔ 八进制转换

1. 十进制 → 八进制

2. 八进制 → 十进制

3、十进制 ↔ 十六进制转换

1. 十进制 → 十六进制

2. 十六进制 → 十进制

4、二进制 ↔ 八进制转换

1. 二进制 → 八进制

2. 八进制 → 二进制

5、二进制 ↔ 十六进制转换

1. 二进制 → 十六进制

2. 十六进制 → 二进制

6、快速转换技巧

7、常见进制对照表

三、C++ 实现进制转换

四、代码解析与关键点

五、应用场景与注意事项

1. 实际应用

2. 注意事项


前言

  在计算机科学领域,进制是数据表示的基础。无论是底层的二进制电路,还是高级编程语言中的数值运算,都离不开进制的概念,本人在日常学习过程中总是对计算机进制的互相转换有点不清楚,今天借助ai以及自己学过的内容进行一个疑问的解答,帮助自己也帮助大家对各进制有什么应用场景以及它们之间相互转换的规则进行梳理

一、各进制的核心作用

1. 二进制(Binary, Base-2)

  • 作用:计算机硬件的基础语言,所有数据在内存和处理器中以二进制形式存储和处理。
  • 特点
    • 仅包含两个数字:0 和 1。
    • 每一位称为一个比特(bit),8 位组成一个字节(Byte)
  • 应用场景
    • 底层编程(如位运算、嵌入式系统)。
    • 网络协议(如 IP 地址、MAC 地址)。

2. 八进制(Octal, Base-8)

  • 作用:早期用于简化二进制表示,每 3 位二进制对应 1 位八进制。
  • 特点
    • 使用数字 0-7。
    • 前缀为0(如0377表示十进制 255)。
  • 应用场景
    • Unix/Linux 系统的文件权限(如755表示读写执行权限)。
    • 早期计算机系统(如 PDP-11)。

3. 十进制(Decimal, Base-10)

  • 作用:人类日常使用的进制,符合直觉的数值表示。
  • 特点
    • 使用数字 0-9。
  • 应用场景
    • 日常计算、财务系统。
    • 高级编程语言的默认数值输入 / 输出。

4. 十六进制(Hexadecimal, Base-16)

  • 作用:现代计算机中最常用的二进制简化表示,每 4 位二进制对应 1 位十六进制。
  • 特点
    • 使用数字 0-9 和字母 A-F(或 a-f)表示 10-15。
    • 前缀为0x(如0xFF表示十进制 255)。
  • 应用场景
    • 内存地址(如0x7FFFFFFF)。
    • 颜色编码(如#FF0000表示红色)。
    • 加密算法(如 MD5、SHA-256 哈希值)。
    • 在进程等待时从status中取得终止信号和退出状态以及是否core dump

              通过status&0x7F(也就是二进制下7个比特位为1:0000 0000 0111 1111)来取得status的前7位也就是把该进程的终止是信号拿到了,通过status右移8位再&0xFF(也就是二进制下8个比特位为1:0000 0000 1111 1111)这样就取得了status次低8位,也就是退出状态,通过status右移7位,再&0x1(0000 0000 0000 0001),这样就能取得在status下第7位的是否core dump标志了

二、进制转换的数学原理

1、十进制 ↔ 二进制转换

1. 十进制 → 二进制

方法:不断除以 2,记录余数,直到商为 0,然后反向排列余数。

示例:将十进制数 25 转换为二进制

  • 25 ÷ 2 = 12 余 1
  • 12 ÷ 2 = 6 余 0
  • 6 ÷ 2 = 3 余 0
  • 3 ÷ 2 = 1 余 1
  • 1 ÷ 2 = 0 余 1
  • 反向排列余数11001
  • 验证:2⁴ + 2³ + 0 + 0 + 2⁰ = 16 + 8 + 1 = 25

2. 二进制 → 十进制

方法:按位加权求和,权重为 2 的幂次(从右到左递增)。

示例:将二进制数 10110 转换为十进制

  • 1×2⁴ + 0×2³ + 1×2² + 1×2¹ + 0×2⁰
  • 16 + 0 + 4 + 2 + 0 = 22

2、十进制 ↔ 八进制转换

1. 十进制 → 八进制

方法:不断除以 8,记录余数,直到商为 0,然后反向排列余数。

示例:将十进制数 53 转换为八进制

  • 53 ÷ 8 = 6 余 5
  • 6 ÷ 8 = 0 余 6
  • 反向排列余数65
  • 验证:6×8¹ + 5×8⁰ = 48 + 5 = 53

2. 八进制 → 十进制

方法:按位加权求和,权重为 8 的幂次(从右到左递增)。

示例:将八进制数 247 转换为十进制

  • 2×8² + 4×8¹ + 7×8⁰
  • 128 + 32 + 7 = 167

3、十进制 ↔ 十六进制转换

1. 十进制 → 十六进制

方法:不断除以 16,记录余数(0-9 或 A-F),直到商为 0,然后反向排列余数。

示例:将十进制数 289 转换为十六进制

  • 289 ÷ 16 = 18 余 1(对应十六进制 1
  • 18 ÷ 16 = 1 余 2(对应十六进制 2
  • 1 ÷ 16 = 0 余 1(对应十六进制 1
  • 反向排列余数121
  • 验证:1×16² + 2×16¹ + 1×16⁰ = 256 + 32 + 1 = 289

2. 十六进制 → 十进制

方法:按位加权求和,权重为 16 的幂次(从右到左递增)。

示例:将十六进制数 0x3F7 转换为十进制

  • 3×16² + 15×16¹ + 7×16⁰
  • 768 + 240 + 7 = 1015

4、二进制 ↔ 八进制转换

1. 二进制 → 八进制

方法:从右到左每 3 位二进制分组,不足 3 位补零,每组转换为对应的八进制数字。

示例:将二进制数 1011010 转换为八进制

  • 分组001 011 010
  • 转换每组:001 → 1,011 → 3,010 → 2
  • 结果132
  • 验证:1×8² + 3×8¹ + 2×8⁰ = 64 + 24 + 2 = 90(与二进制 1011010 对应的十进制一致)

2. 八进制 → 二进制

方法:将每个八进制数字展开为对应的 3 位二进制数。

示例:将八进制数 72 转换为二进制

  • 展开每位:7 → 111,2 → 010
  • 结果111010

5、二进制 ↔ 十六进制转换

1. 二进制 → 十六进制

方法:从右到左每 4 位二进制分组,不足 4 位补零,每组转换为对应的十六进制数字。

示例:将二进制数 11010110 转换为十六进制

  • 分组1101 0110
  • 转换每组:1101 → D,0110 → 6
  • 结果0xD6
  • 验证:D×16¹ + 6×16⁰ = 13×16 + 6 = 214(与二进制 11010110 对应的十进制一致)

2. 十六进制 → 二进制

方法:将每个十六进制数字展开为对应的 4 位二进制数。

示例:将十六进制数 0x2A 转换为二进制

  • 展开每位:2 → 0010,A → 1010
  • 结果00101010 → 简化为 101010

6、快速转换技巧

  1. 二进制 → 八进制 / 十六进制

    • 二进制转八进制:每 3 位一组,直接映射(如 111 → 7)。
    • 二进制转十六进制:每 4 位一组,直接映射(如 1111 → F)。
  2. 八进制 / 十六进制 → 二进制

    • 八进制转二进制:每 1 位展开为 3 位(如 7 → 111)。
    • 十六进制转二进制:每 1 位展开为 4 位(如 F → 1111)。
  3. 多进制通用转换
    任何进制之间的转换都可以通过十进制作为中间桥梁进行:
    A进制 → 十进制 → B进制

7、常见进制对照表

十进制二进制八进制十六进制
0000000
1000111
2001022
3001133
4010044
5010155
6011066
7011177
81000108
91001119
10101012A
11101113B
12110014C
13110115D
14111016E
15111117

F

三、C++ 实现进制转换

以下是完整的 C++ 代码实现,包含了各进制之间的相互转换函数:

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>


// ===== 十进制转换为其他进制 =====
std::string decToBin(int num) 
{
    if (num == 0) return "0";
    std::string result;
    bool isNegative = num < 0;
    num = abs(num);
    
    while (num > 0) {
        result += (num % 2) ? '1' : '0';
        num /= 2;
    }
    
    if (isNegative) result += '-';
    std::reverse(result.begin(), result.end());
    return result;
}



std::string decToOct(int num) 
{
    if (num == 0) return "0";
    std::string result;
    bool isNegative = num < 0;
    num = abs(num);
    
    while (num > 0) {
        result += (num % 8) + '0';
        num /= 8;
    }
    
    if (isNegative) result += '-';
    std::reverse(result.begin(), result.end());
    return result;
}


std::string decToHex(int num) 
{
    if (num == 0) return "0";
    std::string result;
    bool isNegative = num < 0;
    num = abs(num);
    
    const char hexChars[] = "0123456789ABCDEF";
    while (num > 0) {
        result += hexChars[num % 16];
        num /= 16;
    }
    
    if (isNegative) result += '-';
    std::reverse(result.begin(), result.end());
    return result;
}



// ===== 其他进制转换为十进制 =====
int binToDec(const std::string& bin) 
{
    int result = 0;
    bool isNegative = false;
    size_t start = 0;
    
    if (bin[0] == '-') {
        isNegative = true;
        start = 1;
    }
    
    for (size_t i = start; i < bin.size(); ++i) {
        result = result * 2 + (bin[i] - '0');
    }
    
    return isNegative ? -result : result;
}



int octToDec(const std::string& oct) 
{
    int result = 0;
    bool isNegative = false;
    size_t start = 0;
    
    if (oct[0] == '-') {
        isNegative = true;
        start = 1;
    }
    
    for (size_t i = start; i < oct.size(); ++i) {
        result = result * 8 + (oct[i] - '0');
    }
    
    return isNegative ? -result : result;
}



int hexToDec(const std::string& hex) 
{
    int result = 0;
    bool isNegative = false;
    size_t start = 0;
    
    // 跳过0x前缀
    if (hex.size() >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) {
        start = 2;
    } else if (hex[0] == '-') {
        isNegative = true;
        start = 1;
    }
    
    for (size_t i = start; i < hex.size(); ++i) {
        char c = toupper(hex[i]);
        int val;
        
        if (c >= '0' && c <= '9') {
            val = c - '0';
        } else if (c >= 'A' && c <= 'F') {
            val = 10 + (c - 'A');
        } else {
            throw std::invalid_argument("Invalid hex character");
        }
        
        result = result * 16 + val;
    }
    
    return isNegative ? -result : result;
}



// ===== 二进制与八进制/十六进制互转 =====
std::string binToOct(const std::string& bin) 
{
    // 补全位数至3的倍数
    std::string padded = bin;
    while (padded.size() % 3 != 0) {
        padded = '0' + padded;
    }
    
    std::string result;
    for (size_t i = 0; i < padded.size(); i += 3) {
        std::string group = padded.substr(i, 3);
        int val = (group[0] - '0') * 4 + (group[1] - '0') * 2 + (group[2] - '0');
        result += std::to_string(val);
    }
    
    return result;
}



std::string binToHex(const std::string& bin) 
{
    // 补全位数至4的倍数
    std::string padded = bin;
    while (padded.size() % 4 != 0) {
        padded = '0' + padded;
    }
    
    std::string result;
    const char hexChars[] = "0123456789ABCDEF";
    
    for (size_t i = 0; i < padded.size(); i += 4) {
        std::string group = padded.substr(i, 4);
        int val = (group[0] - '0') * 8 + (group[1] - '0') * 4 + 
                  (group[2] - '0') * 2 + (group[3] - '0');
        result += hexChars[val];
    }
    
    return result;
}



std::string octToBin(const std::string& oct) 
{
    std::string result;
    for (char c : oct) {
        int val = c - '0';
        std::string bin = "";
        for (int i = 2; i >= 0; --i) {
            bin += ((val >> i) & 1) ? '1' : '0';
        }
        result += bin;
    }
    
    // 移除前导零
    size_t firstNonZero = result.find_first_not_of('0');
    return (firstNonZero != std::string::npos) ? 
           result.substr(firstNonZero) : "0";
}



std::string hexToBin(const std::string& hex) 
{
    std::string result;
    size_t start = 0;
    
    // 跳过0x前缀
    if (hex.size() >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X')) {
        start = 2;
    }
    
    for (size_t i = start; i < hex.size(); ++i) {
        char c = toupper(hex[i]);
        int val;
        
        if (c >= '0' && c <= '9') {
            val = c - '0';
        } else if (c >= 'A' && c <= 'F') {
            val = 10 + (c - 'A');
        } else {
            throw std::invalid_argument("Invalid hex character");
        }
        
        std::string bin = "";
        for (int i = 3; i >= 0; --i) {
            bin += ((val >> i) & 1) ? '1' : '0';
        }
        result += bin;
    }
    
    // 移除前导零
    size_t firstNonZero = result.find_first_not_of('0');
    return (firstNonZero != std::string::npos) ? 
           result.substr(firstNonZero) : "0";
}



// ===== 主函数演示 =====
int main() {
    // 测试数据
    int decNum = 255;
    std::string binNum = "11010110";
    std::string octNum = "377";
    std::string hexNum = "0xFF";
    
    // 十进制转换
    std::cout << "十进制转二进制: " << decNum << " → " << decToBin(decNum) << std::endl;
    std::cout << "十进制转八进制: " << decNum << " → " << decToOct(decNum) << std::endl;
    std::cout << "十进制转十六进制: " << decNum << " → " << decToHex(decNum) << std::endl;
    
    // 其他进制转十进制
    std::cout << "二进制转十进制: " << binNum << " → " << binToDec(binNum) << std::endl;
    std::cout << "八进制转十进制: " << octNum << " → " << octToDec(octNum) << std::endl;
    std::cout << "十六进制转十进制: " << hexNum << " → " << hexToDec(hexNum) << std::endl;
    
    // 二进制与八进制/十六进制互转
    std::cout << "二进制转八进制: " << binNum << " → " << binToOct(binNum) << std::endl;
    std::cout << "二进制转十六进制: " << binNum << " → " << binToHex(binNum) << std::endl;
    std::cout << "八进制转二进制: " << octNum << " → " << octToBin(octNum) << std::endl;
    std::cout << "十六进制转二进制: " << hexNum << " → " << hexToBin(hexNum) << std::endl;
    
    return 0;
}

 

四、代码解析与关键点

  1. 十进制转其他进制

    • 使用循环不断除以目标进制基数,保存余数后反向排列。
    • 处理负数时,先取绝对值,最后添加符号位。
  2. 其他进制转十进制

    • 按位加权求和,注意处理前缀(如0x)和符号位。
  3. 二进制与八进制 / 十六进制互转

    • 二进制 → 八进制 / 十六进制:按 3 位或 4 位分组,直接映射。
    • 八进制 / 十六进制 → 二进制:每 1 位展开为 3 位或 4 位。
  4. 字符串处理

    • 使用std::reverse反转字符串。
    • 处理前导零时,确保结果正确性(如0不会被移除)。

五、应用场景与注意事项

1. 实际应用

  • 嵌入式开发:直接操作二进制位(如寄存器配置)。
  • 网络编程:解析 IP 地址、端口号等二进制数据。
  • 密码学:处理哈希值、密钥等十六进制表示。

2. 注意事项

  • 溢出问题:转换大数值时需注意数据类型范围(如int vs long long)。
  • 字符大小写:十六进制字符需统一处理(如Aa均视为 10)。
  • 前缀处理:八进制(0)和十六进制(0x)的前缀需特殊处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值