利用递归解决进制转换问题

来源:互联网 发布:英语专业就业前景知乎 编辑:程序博客网 时间:2024/05/16 18:58

放寒假的时候博主在家学如何编程实现十进制与任意进制之间的转换,在网上搜集的了很多种方法,但奈何自己太渣好多都看的云里雾里,而且普遍代码都比较长...然而今天博主再看递归部分的时候突然发现这道题的代码其实可以用递归很简洁的实现,希望对大家能有所帮助。


问题描述:

将十进制数转化为任意进制按格式并输出。

输入格式:输入两个数,第一个数位需要转化的十进制数字,第二个数为要转成的进制数(2.8.16等一般不超过16);

输出格式:转化成要求进制的格式输出;


完整代码:

#include <iostream>
#include <string.h>
void change(char *s, int n, int base)
{
    char rule[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    int len;
    if (n == 0)
        return;
    change(s, n/base, base);
    len = strlen(s);
    s[len] = rule[n % base];
    s[len + 1] = '\0';
    return;
}
int main()
{
    int number, base;
    char s[80] = {'\0'};
    std::cin >> number >> base;
    change(s, number, base);
    std::cout << s << std::endl;
    return 0;
}

分析:

1、了解进制的同学都知道,所谓的几进制就是满几进1,比如2进制就是满2进1,10进制就是满10进1 以此类推即可。

2、有了前期知识,我们可以来思考一下,如果不编程,我们如何求一个十进制数的X进制?

例如 我们有一个十进制数25,求它的X = 2进制;

 可以用短除法:25/2 =12.....1    

         12/2 = 6......0      

            6/2 = 3........0      

                  3/2 = 1........1      

                1/2 = 0........1

所以:十进制(25) =   二进制(11001);

当x取其他值的时候把上面的2换成对应的值就好,方法都是一样的;

 3、通过上述的思考过程我们不难发现每一次计算,问题规模都在缩小,上一步的计算结果会在下一步的计算中使用,当计算结果为0时表示计算结束即可停止计算;多么完美的递归实现条件呀,哈哈;

 4、接下来我们来考虑如何用代码实现它:

考虑输入:需要申请两个变量,存放输入需要的转换的数字int n,存放转化后的进制数int base

考虑输出:我们最后输出的转化后的base进制格式,如果为二进制的话,可能会出现8,9位的现象,所以显然不能定义为int型变量,我们在这里可以定义一个字符型的数组char s[80],因为不知道会有多少位输出,所以先定义成80,(如果定义的过少的话有可能后面的值存不进来。当然你也可以定义成100,甚至1000 as you like 只多不少就行,当然还是要适当考虑内存空间多出来的部分会被浪费掉);数组定义之后肯定要进行下标访问,所以还需要定义一个变量int len,表示数组下标;

考虑结果:我们在上一步考虑结果的时候定义了一个存放结果的数组s,那我们到底应该把什么存进去?显而易见 求余计算后的余数,可是如果直接s[len] = n % base, 万一我们的base > 10,那岂不是会放进去一个大于十的数字给字符数组,显然不合适,我们都知道在进制表示的时候大于9之后用的是ABCDEF表示之后的数字,所以这部分就不能直接写s[len] = n % base,不知道大家有没有发现这样一个规律求余的结果刚好对应了一个从零开始的数组下标,再加上之前我们做日期题得到的启发 我们就可以在这里定义一个存放结果的数组(因为我们存结果的是char 所以为了方便起见,这里这个结果表我们也定义成char)charrule[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

所以我们就有s[len] =rule[n % base] 这里还有个问题就是len的取值?比如我们之前已经存进去一个,结果数组长度为1,结果了所以这次应该存到第二个位置也就是s[1],可以这样写len = strlen(s);

接下来写递归:既然知道了可以用递归的思想做,那就可以先思考一下递归所需要东西:

出口(结束条件):当数字除以进制基数商为0的时候就证明已经计算完成了 ,所以出口就可以表示为:

if (n % base == 0) return;

递归调用:change( ?, ?, ? )要传什么参数进去?首先因为每一次都要用到结果赋值操作,所以要把s数组传进去;接下来缩小问题规模,比如上一次我们算的是25/2,那再调用的时候就应该缩小一步所以就应该是把25/2 = 12传进去;然后还需要一个base表示转换的进制基数;所以我们就可以这样表示change(s,n/base,base)

现在基本上上已经准备好啦, 我们可以开始写啦:

#include <iostream>

#include <string.h>     // because we need strlen();

void change(char *s, int n, int base)

{

char rule[] =  {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

int len;

if (n % base == 0) return;

len = strlen(s);

s[len] =rule[n % base] ;

s[len +1] = ' \0 '; // becaue when s[] =' \0 'string char[] is over;

return ;

}

int main()

{

int n, base;

char s[80] = {'\0'};

std::cin >> n >> base;

change(s, n, base);

std::cout << s << std::endl;

return 0;

}

好啦 这个问题就这样解决啦 4不4很简单 哈哈

希望这样的思考过程能帮助到一些人

因为这个代码只能实现10到其他的转换,并没有真正意义上实现进制之间的任意转化,所以过一段时间博主计划推出一个可以任意转换的代码,用栈实现的思想过程,祈祷这段时间博主好好学习,早日学会栈 哈哈。

0 0
原创粉丝点击