进制转换总结(C++)

之前考研复试机试的时候就碰到了涉及十进制和二进制转换的问题,当时没做出来,心态很崩溃,现在要认真沉淀。经过这两天的学习,我总结了一下进制转换的要点,与大家分享,共勉!!!

进制转换类题型可以分为两种:

1.十进制转换成K进制

2.K进制转换成十进制

这类题主要涉及的数据结构类型有:int变量,int数组,char变量,char数组等。

主要涉及的知识点有:/运算、%运算、对字符数组的理解、字符与数字的相互转化、对ASCII码的理解等等。

——————————————————————————————————————————

对于十进制转换成K进制的题:

首先考虑基本方法,使用除K取余法。然后选取算法需要的数据结构类型,这里主要需要考虑的是输入输出的数据结构。输入的话,就是一个十进制的整型数,根据题目选择int或者long long即可。输出的话,我们选择一个字符数组或者整型数组(比如十六进制涉及‘A','B','C','D','E','F'可以使用字符数组,当然也可以选择使用整型数组先存储,等到输出时再将整数输出为对应的A,B,C,D,E,F即可,而二进制则只涉及0,1,可以使用整型数组)。

以《算法笔记》中的一道练习题为例。题目如下:

下面是我的解题代码:

#include <cstdio>

#include <cstring>

using namespace std;  //**************多余了

char a[15];

int main(){

    int n,k;

    scanf("%d%d",&n,&k);

    int i = 0;

    memset(a,'a',sizeof(a)); //*****************有更好的写法

    do{

        if(n%k < 10){a[i++] = n % k + '0';}

        if(n%k == 10){a[i++] = 'A';} //************有更好的写法

        if(n%k == 11){a[i++] = 'B';} //************同上

        if(n%k == 12){a[i++] = 'C';} //*************同上

        if(n%k == 13){a[i++] = 'D';} //*************同上

        if(n%k == 14){a[i++] = 'E';} //*************同上

        if(n%k == 15){a[i++] = 'F';} //*************同上

        n /= k;

    }while(n > 0);

    for(int i=14; i >= 0; i--){

        if(a[i] != 'a'){

            printf("%c",a[i]);

        }

    }

    return 0;

}

后来查看了题解的参考代码以及做了一些字符串的练习之后,发现我的代码虽然运行通过,但是简洁性很差,对字符数组的理解也不是很够。

题解代码如下:

#include <cstdio>

const int MAXN = 11;
int radixK[MAXN], len = 0;

int main() {
    int radix10, k;
    scanf("%d%d", &radix10, &k);
    do {
        radixK[len++] = radix10 % k;
        radix10 /= k;
    } while (radix10 > 0);
    for (int i = len - 1; i >= 0; i--) {
        if (radixK[i] <= 9) {
            printf("%d", radixK[i]);
        } else {
            printf("%c", radixK[i] - 10 + 'A');
        }
    }
    return 0;
}

首先,我采取的输出字符数组的方法是循环判断条件,如本体,K进制里不可能有小写字母,所以我先将字符数组所有元素初始化为小写字母a,输出是将非a字符输出。当然,以我的方法也可以优化,不需要在一开始将字符数组所有元素初始化为小写字母a,一开始定义它的类型时,字符数组中的每个元素就已经有值了,是‘\0’即空字符NULL。后面输出就将非'\0'输出即可。

题解采用的是计数输出法,即在除K取余过程将模存入数组时就对下标进行计数,(其实我的代码中也计数了,a[i++]中的i可以充当计数器,不过我后来代码中又用了i,还重新赋值了,也没有想到跳出循环后的i值还有实际用处,说明我的代码其实挺乱的,对每个变量的使用也不是很充分)然后用for循环输出所求的字符即可。

对下面这部分代码:

        if(n%k < 10){a[i++] = n % k + '0';}

        if(n%k == 10){a[i++] = 'A';} //************有更好的写法

        if(n%k == 11){a[i++] = 'B';} //************同上

        if(n%k == 12){a[i++] = 'C';} //*************同上

        if(n%k == 13){a[i++] = 'D';} //*************同上

        if(n%k == 14){a[i++] = 'E';} //*************同上

        if(n%k == 15){a[i++] = 'F';} //*************同上

也可以优化为: 

if(n%k < 10){a[i++] = n % k + '0';} //<1>

else{a[i++] = n % k - 10 + 'A';} //<2>

这里我对一些我之前不熟悉的字符及字符数组相关知识点总结如下:

1.字符数组定义之后(如char a[15];)会自动将所有元素初始化为空字符'\0'(也就是NULL)。

顺嘴一提,空字符仍然是字符,不是空格,它常用来作为字符串的结束标志。

2. 字符可以比较,也可以加减计算。需要知道0~9数字的ASCII码是连续的,A~Z大写字母的ASCII码是连续的, a~z小写字母的ASCII码是连续的。再记住0~9数字的ASCII码 整体小于 A~Z大写字母的ASCII码 整体小于  a~z小写字母的ASCII码。也不用记得什么大写字母比小写字母ASCII码小32,直接用'a'-'A'就出来了。

因为字符就是用ASCII码存储和进行加减计算的,因此数字0~9转化为字符‘0’~‘9’只需要+‘0’就行了,这个‘0’虽然我们看作‘0’字符,但它在计算机里是ASCII码(十进制表示为48,二进制表示为00110000),因此48+0还是48,也就是‘0’+0还是‘0’。同理,将字符‘0’~‘9’转换为数字0~9只需要-‘0’就行了,比如字符‘1’的ASCII码是49,49-48就是1。那你可能会好奇,为什么这里的1就是数字1呢而不是ASCII码的1呢。其实我也好奇。然后我想通了。就是你用于存储的数据结构是int,计算机就会将00110000解释为48,你用于存储的数据结构是char,计算机就会将00110000看作ASCII码通过ASCII码对照表将它解释为字符‘0’。

那么数字10转换为字符'A',数字11转换为字符'B',...你会了吗?请思考一下。

没错 char c = number - 10 + 'A';即可实现上面所有啦。(当然也可以char c = number - 11 + 'B';...)

小技巧:想看哪个字符的ASCII码直接运行一下下面一行代码就可以了:

如printf(" %d",'A');就会显示字符‘A’的ASCII码。其中%d代表将'A'以整型输出,相当于把该字符用int型数据结构解释。

——————————————————————————————————————————

对于K进制转换为十进制的题:

首先依然先思考基本方法,可以使用逐位累加法。以2进制1011为例,十进制等于1*2的3次方 + 0*2的2次方 + 1*2的1次方 + 1*2的0次方。

然后考虑输入输出所需要用到的数据类型,输入使用整型变量或者字符数组(如果是二进制用1个整型变量就行了,不需要使用数组;如果是十六进制,则需要使用字符数组,因为整型变量无法存储A,B,C,D,E,F)。再就是输出的数据结构类型,输出一个十进制数,因此只需要使用一个整型变量即可。

由于这里输入有两种情况,整型变量or字符数组,因此这里我分开说:

1.对于一个整型如int数据结构存储的值,我们要获取它的某一位数字需要用到两个知识点:

一是计算机整型的除法运算‘/’;二是计算机整型的模运算‘%’

除法运算‘/’就是获取除法的商,如5/3等于1,2/3等于0。

模运算‘%’就是获取除法的余数,如5%3等于2,2%3等于2。

考虑一个数 123456789

123456789 / 10 等于 12345678;

123456789 % 10 等于 9。

你看出什么来了吗?12345678|9,对一个数,模10得最后1位数,除10得其余前面所有位。

那么取1位数就可以这样。(除取左,模取右

取9:123456789 % 10 —— 12345678|9

取8:(123456789 / 10)%10——1234567|8

取7:(123456789 / 100)% 10——123456|7

取6:(123456789 / 1000)% 10——12345|6

......

取2:123456789 / 10000000)% 10——1|2

取1:123456789 / 100000000——1

 2.对于字符数组,我们获取它的1个字符很简单,遍历数组就可以访问到数组的每一位字符。对于十六进制数,将它存在字符数组中后,将各个字符取出时转化为对应整型数字在进行累加计算即可。

对整型变量or字符数组取1位数的总结

1.整型变量循环用模运算取个位数。(不管你规定它是二进制还是十进制还是什么K进制,我们计算机除法和模运算都是十进制运算,把它看作十进制来处理)

2.字符数组访问数组元素转化为对应数字即可。

这篇文章就写到这里啦~希望下次遇到涉及进制转换的题,我们都能成功做出来哦。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值