C++算法·进制转换

引言

基础的十进制,即逢十进一

日常生活中用的就是十进制(不包括时间、角度等)

还有电脑中的机械语言用的二进制,即逢二进一

例如(101)2(101)2(101)2表示二进制101101101,即十进制的(5)10(5){10}(5)10

至于怎么转换进制,就是本文要讲的内容

定义&规律

引言中有提到,有多种进制,如十进制、二进制等

具体的xxx进制就是每逢xxx进一位

我们用基础的十进制列表与八进制对比下

十进制 八进制
(0)10(0)_{10}(0)10 (0)8(0)_8(0)8
(1)10(1)_{10}(1)10 (1)8(1)_8(1)8
(2)10(2)_{10}(2)10 (2)8(2)_8(2)8
(3)10(3)_{10}(3)10 (3)8(3)_8(3)8
(4)10(4)_{10}(4)10 (4)8(4)_8(4)8
(5)10(5)_{10}(5)10 (5)8(5)_8(5)8
(6)10(6)_{10}(6)10 (6)8(6)_8(6)8
(7)10(7)_{10}(7)10 (7)8(7)_8(7)8
(8)10(8)_{10}(8)10 (10)8(10)_8(10)8
(9)10(9)_{10}(9)10 (11)8(11)_8(11)8
(10)10(10)_{10}(10)10 (12)8(12)_8(12)8
(11)10(11)_{10}(11)10 (13)8(13)_8(13)8
.................. ..................

通过列表可以发现,在0∼70 \sim 70∼7的十进制时,八进制与十进制的表示方法相同

但是到888时,八进制向左进位,最右边那一位变成000

十进制则到101010才进位,这里就可以发现逢xxx进111的规律了

下面来些例题:

例题1:二进制 → 十进制 (基础)

题目: 将二进制数 1101.101 转换为十进制数。

解答:

转换分为整数部分(1101)和小数部分(.101)。

  1. 整数部分 (1101):从右向左,每位乘以2的位次幂(从0开始)。

    • 1 × 2⁰ = 1 × 1 = 1
    • 0 × 2¹ = 0 × 2 = 0
    • 1 × 2² = 1 × 4 = 4
    • 1 × 2³ = 1 × 8 = 8
    • 整数部分总和:8 + 4 + 0 + 1 = 13
  2. 小数部分 (.101):从左向右,每位乘以2的负位次幂(从-1开始)。

    • 1 × 2⁻¹ = 1 × (1/2) = 0.5
    • 0 × 2⁻² = 0 × (1/4) = 0
    • 1 × 2⁻³ = 1 × (1/8) = 0.125
    • 小数部分总和:0.5 + 0 + 0.125 = 0.625
  3. 合并结果 :13 + 0.625 = 13.625
    答案: (1101.101)₂ = (13.625)₁₀


例题2:十进制 → 二进制 (基础)

题目: 将十进制数 18.625 转换为二进制数。

解答:

转换分为整数部分(18)和小数部分(.625)。

  1. 整数部分 (18):用"除2取余,逆序排列"法。

    • 18 ÷ 2 = 9 ... 余0 (最低位)
    • 9 ÷ 2 = 4 ... 余1
    • 4 ÷ 2 = 2 ... 余0
    • 2 ÷ 2 = 1 ... 余0
    • 1 ÷ 2 = 0 ... 余1 (最高位)
    • 将余数从下往上排列:10010
    • 所以 (18)₁₀ = (10010)₂
  2. 小数部分 (.625):用"乘2取整,顺序排列"法。

    • 0.625 × 2 = 1 .25 ... 取整1 (最高位)
    • 0.25 × 2 = 0 .5 ... 取整0
    • 0.5 × 2 = 1 .0 ... 取整1 (最低位)
    • 将整数部分从上往下排列:.101
    • 所以 (0.625)₁₀ = (.101)₂
  3. 合并结果10010.101
    答案: (18.625)₁₀ = (10010.101)₂


例题3:八进制 ↔ 二进制 (快捷方法)

题目: 将八进制数 57.24 转换为二进制数。

解答:

八进制和二进制有天然对应关系(1位八进制数对应3位二进制数)。

  1. 将每位八进制数拆开:5, 7, ., 2, 4
  2. 查阅或计算每位对应的3位二进制数:
    • 5 → 101
    • 7 → 111
    • 2 → 010
    • 4 → 100
  3. 按顺序组合起来:101111.010100
  4. 可以省略末尾不必要的0,写成 101111.0101
    答案: (57.24)₈ = (101111.0101)₂

逆向练习: 将二进制数 1100101.01101 转换为八进制数。

  1. 以小数点为中心,向左向右每3位一组,不足的补0。
    • 整数部分 1100101001 100 101 (补两个0)
    • 小数部分 .01101.011 010 (补一个0)
  2. 将每3位二进制数转换为一位八进制数:
    • 001 → 1
    • 100 → 4
    • 101 → 5
    • 011 → 3
    • 010 → 2
  3. 组合结果:145.32
    答案: (1100101.01101)₂ = (145.32)₈

例题4:十六进制 ↔ 十进制 (综合)

题目: 将十六进制数 2A.8 转换为十进制数。

解答:

转换方法与二进制转十进制类似,但基数为16。注意字母 A 表示10。

  1. 整数部分 (2A):从右向左,每位乘以16的位次幂。

    • A(10) × 16⁰ = 10 × 1 = 10
    • 2 × 16¹ = 2 × 16 = 32
    • 整数部分总和:32 + 10 = 42
  2. 小数部分 (.8):从左向右,每位乘以16的负位次幂。

    • 8 × 16⁻¹ = 8 × (1/16) = 0.5
  3. 合并结果 :42 + 0.5 = 42.5
    答案: (2A.8)₁₆ = (42.5)₁₀


例题5:任意进制 → 十进制 (进阶)

题目: 将五进制数 123.4 转换为十进制数。

解答:

方法通用,只需将基数改为5。

  1. 整数部分 (123)₅:从右向左,每位乘以5的位次幂。

    • 3 × 5⁰ = 3 × 1 = 3
    • 2 × 5¹ = 2 × 5 = 10
    • 1 × 5² = 1 × 25 = 25
    • 整数部分总和:25 + 10 + 3 = 38
  2. 小数部分 (.4)₅:从左向右,每位乘以5的负位次幂。

    • 4 × 5⁻¹ = 4 × (1/5) = 0.8
  3. 合并结果 :38 + 0.8 = 38.8
    答案: (123.4)₅ = (38.8)₁₀


总结与技巧

转换类型 关键方法 技巧
N进制 → 十进制 按权展开求和 *①\text{\red{*}{\small{①}}}*①对每一位×N位数×N^{位数}×N位数次方
十进制 → N进制 整数除N取余,小数乘N取整 整数部分倒序,小数部分正序
二进制 ↔ 八进制 三位一组 八进制是二进制的简写形式
二进制 ↔ 十六进制 四位一组 十六进制是二进制的更简形式

*\text{\red{*}}*部分进行解释(即注释)

①如(101)2(101)_2(101)2展开得1×20+0×21+1×22=1+2+4=71×2^0+0×2^1+1×2^2=1+2+4=71×20+0×21+1×22=1+2+4=7

对于N进制转M进制

建议是转为十进制或者二进制再转化


------例题由DeepSeek生成

(奇妙的MarkDownMarkDownMarkDown和符号我也看得迷糊)

总结是自己写的


在C++中的运用

可以用string数组储存,然后逐位提取进行计算,最后再计算为其他进制

即可实现进制转换

给个好玩的思路:可以用二进制做加密器

代码放末尾

例:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int z2_10(string a){//二进制转十进制 
	int len=a.size();//长度
    int answer=0;//结果 
    int b=1;//从最低位开始,权重初始为1
    for(int i=len-1;i>=0;i--){
        if(a[i]=='1') {
            answer+=b;
        }
        b*=2;//每向左移动一位,权重乘以2
    }
    return answer;
}
int main(){
	string x;
	cin>>x;
	cout <<z2_10(x);
	return 0;
}

~ 完结撒花完结撒花完结撒花 ~

附:这期没有题单

给的是较为基础的例题

下一篇预告:邻接表/...
加密器实现

我方和对方都要有的程序

cpp 复制代码
#include<bits/stdc++.h>
#include <locale>
using namespace std;
int z2_10(string a){//二进制转十进制 
    int len=a.size();//长度
    int answer=0;//结果 
    int b=1;//从最低位开始,权重初始为1
    for(int i=len-1;i>=0;i--){
        if(a[i]=='1') {
            answer+=b;
        }
        b*=2;//每向左移动一位,权重乘以2
    }
    return answer;
}
string z10_2(int x){//十进制转二进制
    if(x==0)return "0";
    string answer="";//结果
    while(x>0){
        int now=x%2;
        //将余数转换为字符并添加到结果中
        answer+=(now+'0');
        // 除以2,继续处理下一位
        x/=2;
    }
    reverse(answer.begin(),answer.end());//反转字符串
    return answer;
}
string ST(const string&str){
    string result="";
    for(unsigned char c:str){
        result+=z10_2(static_cast<int>(c));
        result+="|";
    }
    if(!result.empty()) {
        result.pop_back();//移除最后一个分隔符
    }
    return result;
}//将字符串转换为UTF-8编码的二进制序列
string TS(const string&Str){
    string result ="";
    string byte="";
    for(char c:Str){
        if(c=='|'){
            if(!byte.empty()){
                int d=z2_10(byte);
                result+=static_cast<char>(d);
                byte="";
            }
        }else{
            byte+=c;
        }
    }
    if(!byte.empty()){
        int d=z2_10(byte);
        result+=static_cast<char>(d);
    }
    return result;
}//将二进制序列转换回字符串
int main(){
    int cse;
    cout <<"输入1加密,输入2破译\n";
    cin>>cse;
    cin.ignore();//清除输入缓冲区 
    if(cse==1){
        string x;
        cin>>x;
        cout <<ST(x)<<endl;
    }else if(cse==2){
        string x,noww="";
        cin>>x;
        string y=TS(x);
        cout <<y<<endl;
    }
    return 0;
}//已经是2.0版本,支持使用中文和符号