论文部分内容阅读
在编程语言的教材中常出现一道求解“水仙花数”的经典问题,即某个三位整数每个数位上数字的三次幂之和等于它本身,比如“153 = 1^3 + 5^3 + 3^3”。其实,水仙花数只是“自幂数”的一种,类似的还有四位数的“四叶玫瑰数”(各数位四次方之和等于本身的数)、五位数的“五角星数”、六位数的“六合数”等。Python语法灵活,可以使用多种方法来完成自幂数的求解,在此略举几种水仙花数的编程方法:
在Python中,运算符“//”代表“整除”运算,即求“整商”;而运算符“%”则是进行“求余”,利用这两种运算符可以将一个多位数的各位数字“分解”提取。在判断一个三位数是否为水仙花数时,首先构建循环结构“for i in range(100,1000):”,百位上的数字提取方法是通过“bai_wei = i//100”求“整商”来完成,比如计算“365//100”,结果就是“3”;十位上的数字提取方法是“shi_wei = (i%100)//10”,即先以100为除数进行“求余”,再将这个中间结果除以10求“整商”,比如计算“(365%100)//10”,会先得到余数65,然后计算“65//10”得到6;个位上的数字提取方法是“ge_wei = i%10”,即除以10求余数,比如“365%10”的结果是5。
循环中的if判断条件是“bai_wei**3 + shi_wei**3 + ge_wei**3 == i:”,即各数位上的数字的三次方之和与该数相等。最后,通过print打印输出变量i的数值,结果得到四个水仙花数:153、370、371和407(如图1)。
因为水仙花数是对一个三位数进行判断,所以直接构建三层循环嵌套来实现从100到999的顺序递增。最外层的“for bai_wei in range(1,10):”控制百位数字循环,注意要从1开始(range()中的起始值和终止值参数为“左闭右开”区间);中间层的十位数字循环是“for shi_wei in range(0,10):”;内部的个位数字循环是“for ge_wei in range(0,10):”,变量my_data是计算存储每个三位数的数值大小,即“bai_wei*100+shi_wei*10+ge_wei”;判断条件与之前相同,最后也是打印输出结果,同样会得到四个水仙花数:153、370、371和407(如图2)。
如果充分利用Python中的各种内置函数,比如map()映射函数,可以非常巧妙地快速“提取”出每个多位数上各数位的数字。首先,同样是通过“for i in range(100,1000):”构建出循环结构;然后使用“序列解包”的方式,同时为三个变量赋值——“bai_wei,shi_wei,ge_wei = map(int,str(i))”,借助map()函数将每个三位数先通过“str(i)”转换为字符串,再将int()函数映射至刚刚生成的字符串序列(迭代对象),就“还原”得到了三个整型数字,分别赋值给三个对应的变量。
接下来仍是使用相同的判断语句和print()输出语句,同样会得到四个水仙花数:153、370、371和407(如图3)。
前两种方法的代码量相似,数位分解法的难点在于使用整除和求余进行组合运算,使用一层循环结构,得到各数位上的数字;循环嵌套法需要构建与数位个数相同的循环数,必须要特别注意循环递进中的代码格式缩进。map()函数映射法比较巧妙,借助str()和int()进行字符串与整型转换,代码量非常精简。
如果题目不是求解水仙花,而是位数更多的自幂数,比如“五角星数”,前两种方法就分别需要多构建两个“整除求余”和两层循環,代码量和复杂度都会增加不少;而map()函数映射法只需要简单地增加“wan_wei”和“qian_wei”两个变量即可,然后修改for循环中的range()起始值(10000,100000)和if条件中的各位数的幂指数(由3改为5),代码量增加得也非常少(仍为4行),最终运行得到三个五角星数:54748、92727和93084(如图4)。
如果再复杂些,比如求解八位的“八仙数”、九位的“重阳数”,大家不妨对比测试一下不同方法的编程效率。
1.“整除”和“求余”数位分解法
在Python中,运算符“//”代表“整除”运算,即求“整商”;而运算符“%”则是进行“求余”,利用这两种运算符可以将一个多位数的各位数字“分解”提取。在判断一个三位数是否为水仙花数时,首先构建循环结构“for i in range(100,1000):”,百位上的数字提取方法是通过“bai_wei = i//100”求“整商”来完成,比如计算“365//100”,结果就是“3”;十位上的数字提取方法是“shi_wei = (i%100)//10”,即先以100为除数进行“求余”,再将这个中间结果除以10求“整商”,比如计算“(365%100)//10”,会先得到余数65,然后计算“65//10”得到6;个位上的数字提取方法是“ge_wei = i%10”,即除以10求余数,比如“365%10”的结果是5。
循环中的if判断条件是“bai_wei**3 + shi_wei**3 + ge_wei**3 == i:”,即各数位上的数字的三次方之和与该数相等。最后,通过print打印输出变量i的数值,结果得到四个水仙花数:153、370、371和407(如图1)。
2.三层循环嵌套法
因为水仙花数是对一个三位数进行判断,所以直接构建三层循环嵌套来实现从100到999的顺序递增。最外层的“for bai_wei in range(1,10):”控制百位数字循环,注意要从1开始(range()中的起始值和终止值参数为“左闭右开”区间);中间层的十位数字循环是“for shi_wei in range(0,10):”;内部的个位数字循环是“for ge_wei in range(0,10):”,变量my_data是计算存储每个三位数的数值大小,即“bai_wei*100+shi_wei*10+ge_wei”;判断条件与之前相同,最后也是打印输出结果,同样会得到四个水仙花数:153、370、371和407(如图2)。
3.map()函数映射法
如果充分利用Python中的各种内置函数,比如map()映射函数,可以非常巧妙地快速“提取”出每个多位数上各数位的数字。首先,同样是通过“for i in range(100,1000):”构建出循环结构;然后使用“序列解包”的方式,同时为三个变量赋值——“bai_wei,shi_wei,ge_wei = map(int,str(i))”,借助map()函数将每个三位数先通过“str(i)”转换为字符串,再将int()函数映射至刚刚生成的字符串序列(迭代对象),就“还原”得到了三个整型数字,分别赋值给三个对应的变量。
接下来仍是使用相同的判断语句和print()输出语句,同样会得到四个水仙花数:153、370、371和407(如图3)。
4.总结
前两种方法的代码量相似,数位分解法的难点在于使用整除和求余进行组合运算,使用一层循环结构,得到各数位上的数字;循环嵌套法需要构建与数位个数相同的循环数,必须要特别注意循环递进中的代码格式缩进。map()函数映射法比较巧妙,借助str()和int()进行字符串与整型转换,代码量非常精简。
如果题目不是求解水仙花,而是位数更多的自幂数,比如“五角星数”,前两种方法就分别需要多构建两个“整除求余”和两层循環,代码量和复杂度都会增加不少;而map()函数映射法只需要简单地增加“wan_wei”和“qian_wei”两个变量即可,然后修改for循环中的range()起始值(10000,100000)和if条件中的各位数的幂指数(由3改为5),代码量增加得也非常少(仍为4行),最终运行得到三个五角星数:54748、92727和93084(如图4)。
如果再复杂些,比如求解八位的“八仙数”、九位的“重阳数”,大家不妨对比测试一下不同方法的编程效率。