进制转换算法(附蓝桥杯例题)

一、进制转换核心原理

1. ‌N进制转十进制‌(按权展开法)

算法步骤‌:

  1. 将N进制数的‌每一位字符转换为对应的十进制数值‌(A-F对应10-15)‌
  2. 从高位到低位‌依次计算:十进制值 = 当前值 × N^权 + 前一步结果
  3. 权值规律‌:第i位的权值为N<sup>i</sup>(i从右往左计数,起始为0)‌

数学公式‌:

代码模板‌(以十六进制转换为10进制为例):

string s = "2021ABCD"; // 十六进制数
ll x = 0;
for (char c : s) {
    int val = isdigit(c) ? c-'0' : toupper(c)-'A'+10;
    x = x * 16 + val; // 累加计算‌:ml-citation{ref="1,3" data="citationList"}
}
cout << x; // 输出539080141

2. ‌十进制转N进制‌(除基取余法)

算法步骤‌:

  1. 用十进制数‌反复除以N‌,记录余数‌
  2. 逆序排列余数‌(最后得到的余数为最高位)‌
  3. 余数>9时用字母A-F表示10-15‌

代码模板(以十进制转换为16进制为例)‌:

int x = 1478; // 十进制数
string ans;
while(x > 0) {
    int rem = x % 9; // 当前余数
    ans += (rem < 10) ? rem+'0' : rem-10+'A';// 如果小于10,就直接减去0
    // 如果大于10的话,就先减去10再加上'A'
    x /= 9;
}
reverse(ans.begin(), ans.end()); // 逆序输出‌
cout << ans; // 输出2022(九进制)


二、经典例题解析

例题1:十六进制转十进制

链接:蓝桥账户中心

题目‌:计算十六进制数 2021ABCD 的十进制值
题目解析:

1.直接用OX20221ABCD输出

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    printf("%d",0X2021ABCD);
    return 0;
}

2.使用模板进行进制的转换:

#include <iostream>
using namespace std;
using ll = long long;
int digit[50];    // 转化之后的各个位数的值

int main()
{
    // 请在此输入您的代码
    string s = "2021ABCD";    // 十六进制数
    for (int i = 0; i < s.length(); i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            digit[i] = s[i] - '0';    // 如果是0-9的数字,就让它转换为整形
        }
        else if (s[i] >= 'A' && s[i] <= 'Z') {
            digit[i] = s[i] - 'A' + 10;   // A-Z的数字都是从10开始的
        }
    }
    ll x = 0;
    for (int i = 0; i < s.length(); i++) {
        x = x * 16 + digit[i];
    }
    cout << x << endl;
    return 0;
}

例题2:九进制转十进制

链接:蓝桥账户中心

计算过程‌:
(2022)9=2×93+0×92+2×91+2×90=1478
代码亮点‌:

  • 直接处理字符到数值的转换
  • 这个不能像上一题使用Ox来做,因为9进制在C++中没有合适的快捷方式输出
  • 无需处理字母字符(九进制无字母)‌
#include <iostream>
#include <cctype>
using namespace std;
using ll = long long;
int digit[50];    // 转化之后的各个位数的值
// 九进制转换为十进制
int main()
{
    string s = "2022";
    for (int i = 0; i < s.length(); i++) {
        if (s[i] >= '0' && s[i] <= '9') {     // 把0-9的字符转化为0-9
            digit[i] = s[i] - '0';
        }
        else if (isalpha(s[i])) {     // 把A-Z转换为10-35,不过这道题不用
            digit[i] = toupper(s[i]) - 'A' + 10;
        }
    }
    ll x = 0;
    for (int i = 0; i < s.length(); i++) {
        x = x * 9 + digit[i];
    }
    cout << x << endl;
    return 0;
}

例题3:通用进制转换

链接:蓝桥账户中心

需求‌:实现N进制到M进制的任意转换
代码设计‌:

  1. N进制→十进制‌:循环累加计算
  2. 十进制→M进制‌:反向存储余数

代码如下:

#include <iostream>
#include <cctype>
#include <algorithm>
using namespace std;
using ll = long long;
char ch[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
  'D', 'E', 'F' };   // 0-15的表示
int digits[15];   // 十进制数位
// 进行进制转换的函数
void solve(int N, int M) {
    // 先将N进制转换为M进制
    string s;   // N进制数
    cin >> s;
    for (int i = 0; i < s.length(); i++) {
        if (isdigit(s[i])) {
            // 判断如果是数字的话,进行转换
            digits[i] = s[i] - '0';
        }
        else if (isalpha(s[i])) {
            // 如果是A-F的字符,就变成超过10的数字
            digits[i] = toupper(s[i]) - 'A' + 10;
        }
    }

    ll x = 0;    // 十进制数
    for (int i = 0; i < s.length(); i++) {    // N进制转换为十进制
        x = x * N + digits[i];
    }
    if (M == 10) {
        // 如果是N进制转换为10进制,就不用再转换了,直接输出
        cout << x << endl;
        return;
    }


    // 再将十进制转换为M进制
    string ans;     // M进制数
    while (x) {
        ans += ch[x % M];
        x /= M;   // 用m整除
    }
    // 整除完之后进行翻转
    reverse(ans.begin(), ans.end());
    cout << ans << endl;

}
int main()
{
    int T;    // 测试数据数量
    cin >> T;
    while (T--)
    {
        int N, M;     // 初始进制数和结果进制数
        cin >> N >> M;
        solve(N, M);
    }

    // 请在此输入您的代码
    return 0;
}


三、算法复杂度对比

转换类型时间复杂度空间复杂度核心操作
N进制→十进制O(n)O(1)按权累加‌
十进制→N进制O(logN x)O(logN x)除基取余‌
通用进制转换O(n + logM x)O(n + logM x)双重转换‌

四、高频考点与易错点

  1. 字符转换错误

    • 必须正确处理A-F/a-f的ASCII转换(toupper()统一大小写)‌67
    • 错误示例:'A'-'0'(应使用'A'-'A'+10
  2. 权值计算方向错误

    • 十六进制数"1A2B"应从左往右计算,而非从右往左‌13
  3. 余数逆序问题

    • 十进制转N进制必须反转余数序列‌45

写在最后:

我们可以在这里学习C++知识:

0voice · GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值