题目1:将非负十进制整数n转换成b进制。(其中b=2~16)
1、题目分析
该问题的主要点在于对整数n进行取模运算,得到余数,同时将n除2,进行递归。
2、递归程序设计思路
递归模型
该递归程序要求将十进制数n转换为二进制数,在这个转换过程中需要对n进行取模,得到余数,同时对n进行除2操作得到下一个要取模的数。因此需要将整数n作为参数,不断的进行取模运算。同理十进制转换为八进制、十进制转换为十六进制也都是进行相应的取模以及除运算。
程序设计
class Transform:
"""进制转换类,将三个方法封装在类中"""
def transform_2(self, n, list_arr=[0]):
"""
二进制转换递归方法,将十进制数转换为二进制
:param n: 传入的十进制数
:param list_arr: 辅助列表,将取模得到的余数放入列表
:return: 返回取余结果的列表
"""
if n != 0: # 函数的递归体
list_arr.append(n % 2)
return self.transform_2(n//2, list_arr) # 递归调用函数
else: # 递归的结束条件
return list_arr[::-1]
def transform_8(self, n, list_arr=[0]):
"""八进制转换递归方法,将十进制数转换为八进制"""
if n != 0:
list_arr.append(n % 8)
return self.transform_8(n // 8, list_arr)
else:
return list_arr[::-1]
def transform_16(self, n, list_arr=[0]):
"""十六进制转换递归方法,将十进制数转换为十六进制"""
if n != 0:
list_arr.append(n % 16)
return self.transform_16(n // 16, list_arr)
else: # 将十六进制中大于10的部分用特定的字符表示
for i in range(len(list_arr)):
if list_arr[i] == 10:
list_arr[i] = 'A'
elif list_arr[i] == 11:
list_arr[i] = 'B'
elif list_arr[i] == 12:
list_arr[i] = 'C'
elif list_arr[i] == 13:
list_arr[i] = 'D'
elif list_arr[i] == 14:
list_arr[i] = 'E'
elif list_arr[i] == 15:
list_arr[i] = 'F'
return list_arr[::-1]
3、递归树
4、非递归方法
非递归方法与递归方法的实现步骤类似,不同的地方是非递归方法是通过循环实现的。
class Transform:
"""进制转换类,将三个方法封装在类中"""
def transform_2(self, n, list_arr=[0]):
"""
二进制转换非递归方法,将十进制数转换为二进制
:param n: 传入的十进制数
:param list_arr: 辅助列表,将取模得到的余数放入列表
:return: 返回取余结果的列表
"""
while n != 0:
list_arr.append(n % 2)
n = n // 2
return list_arr[::-1]
def transform_8(self, n, list_arr=[0]):
"""八进制转换非递归方法,将十进制数转换为八进制"""
while n != 0:
list_arr.append(n % 8)
n = n // 8
return list_arr[::-1]
def transform_16(self, n, list_arr=[0]):
"""十六进制转换非递归方法,将十进制数转换为十六进制"""
while n != 0:
list_arr.append(n % 16)
n = n // 16
for i in range(len(list_arr)): # 将十六进制中大于10的部分用特定的字符表示
if list_arr[i] == 10:
list_arr[i] = 'A'
elif list_arr[i] == 11:
list_arr[i] = 'B'
elif list_arr[i] == 12:
list_arr[i] = 'C'
elif list_arr[i] == 13:
list_arr[i] = 'D'
elif list_arr[i] == 14:
list_arr[i] = 'E'
elif list_arr[i] == 15:
list_arr[i] = 'F'
return list_arr[::-1]
5、代码测试
将十进制数1024传入,分别进行2,8,16进制转换的测试。
二进制
八进制
十六进制
自定义异常处理机制的测试
题目2:
任何一个正整数都可以用2的幂次方表示。
137=27+23+2^0
同时约定幂次方用括号来表示,即ab 可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7= 22+2+20 (21用2表示)
3=2+2^0
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=2^10 +2^8 +2^5 +2+2^0
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入:正整数(n≤20000)
输出:符合约定的n的0,2表示(在表示中不能有空格)
输入格式 Input Format
一个正整数
输出格式 Output Format
符合约定的n的0,2表示(在表示中不能有空格)
样例输入 Sample Input
73
样例输出 Sample Output
2(2(2)+2)+2(2+2(0))+2(0)
1、题目分析:该题的关键点在于如何记录递归的次数,以及对递归次数的再次递归,最终实现全部由2和0表示的一个整数。
2、递归模型
该递归最终是将一个正整数全部分解成由2和0表示的表达式,因此该正整数需要进行除2递归,直至达到1,此时再对递归深度进行判断,总共有三种情况,递归深度分别为0,1,2,默认当递归次数大于2时对递归深度再次进行递归,将递归深度的次数也用用0和2表示。
3、算法设计思路
该程序首先对正整数进行,递归运算,然后在对递归深度进行递归,最后对中间过程的数进行奇偶性判断,再按照包含2和0的指定格式输出。
//n为操作数,deep为递归深度
void number_operation(int n, int deep)
{
if (1 == n) //递归结束条件
{
//将deep用0和2表示
switch(deep)
{
case 0:cout<<"2(0)";break;
case 1:cout<<"2";break;
case 2:cout<<"2(2)";break;
default:
cout<<"2(";
number_operation(deep,0);
cout<<")";
}
}
else
{
//n除以2,递归深度加1
number_operation(n/2, deep+1);//递归体
//如果模2有余数,则为2^deep
if (1 == n%2)
{
//将deep用0和2表示
switch(deep)
{
case 0:cout<<"+2(0)";break;
case 1:cout<<"+2";break;
case 2:cout<<"+2(2)";break;
default:
cout<<"+2(";
number_operation(deep,0);
cout<<")";
}
}
}
}
4、调试及测试
输入1024,对该过程进行测试,刚开始递归深度为0
当递归十次,即递归深度的次数为10,n变为1,然后对递归深度再次进行递归。
当对递归深度进行递归时,传入的参数为上层递归得到递归深度,即为10,同时将递归深度置为0,重新开始计数。
最后得到最终结果,结果表示正确,说明该程序可以正确运行。
5、总结
通过这次对十进制数转换为2进制和将任意一个正整数使用0和2表示的递归程序的练习,不仅学到了关于递归的更多方法,而且总结得到了关于递归更深的认识。学会了使用递归树表示递归程序,递归程序可以大大减少平时使用循环进行运算的工作量,同时递归程序在运行过程也很容易出错,往往出现在对参数的设置中,调试起来也是比较麻烦,但总的来说通过递归可以更方便的处理一些较复杂的难题,如汉诺塔问题、八皇后问题,这些都不是可以简单的通过循环可以实现的。因此,想要熟练的使用递归,还需要在学习中对递归多加练习。