100个python算法超详细讲解:阿姆斯特朗数

1.问题描述
如果一个整数等于其各个数字的立方和 , 则该数称为“阿姆斯特朗
数”(亦称为自恋性数) 。如153=1 3 +5 3 +3 3 就是一个“阿姆斯特朗
数” 。试编程求1000以内的所有“阿姆斯特朗数” 。
2.问题分析
“阿姆斯特朗数”与3.2节中的“水仙花数”的不同在于 , 前者并没有
规定几位数 , 从两者的定义来看 , “水仙花数”可以看作是“阿姆斯特朗
数”的一个子集 。对于这类问题的算法与“水仙花数”类似 , 需要把每一
位分离出来 , 然后比较其立方和与原数是否相等 。
3.算法设计
本题求的是1000以内满足条件的数 , 从数的位数来说可以分为一
位数、两位数及三位数 。这样可以根据数的位数不同分别求出不同范
围内的“阿姆斯特朗数” , 即一位数(1~9)、两位数(10~99)和三
位数(100~999)分别用一个循环语句来实现 。
上述方法有其局限性 , 如果题目改成求1 000 000以内甚至更大范
围的话 , 程序里面会有多个循环 , 不但程序看起来烦琐 , 写起来也费
事 , 更重要的是每个循环体做的事情都是一样的:将数的每一位拆
分 。对于这种重复的事情可以考虑用循环将其简化 。对于一个数无论
它的位数是多少 , 如果要将其拆分 , 要么按从低位到高位的顺序 , 要
么按从高位到低位的顺序 。本题按从低位到高位的顺序进行拆分 。
从低位到高位进行拆分 , 每次拆分的都是当前数的个位 , 可以用
当前数n对10求模 , 即n , 这样最后一位就被分离出来;再次分离的
是原数的次低位 , 对于次低位 , 要想办法让其成为新数的最低位 , 可
【100个python算法超详细讲解:阿姆斯特朗数】采用原数n对10求商的方法 , 即n//10 。其他位置的数据求法同上 。
题目给出的数据最多三位 , 我们可以定义三个变量分别来存储原
数的个位、十位和百位 , 也可以用数组来存储 , 数组的长度为3 。
4.确定程序框架
程序流程图如图3.6所示 。
#!/usr/bin/python3# -*- coding: utf-8 -*-# @author : liuhefei# @desc: 阿姆斯特朗数if __name__ == "__main__":a = [0, 0, 0] # 列表a用来存储被拆分的数的个位、十位和百位print("1000以内的阿姆斯特朗数:")for i in range(2, 1000):t = 0k = i# 按从低位到高位的顺序拆分数while k:a[t] = k % 10k = k // 10t += 1sum = a[0]**3 + a[1]**3 + a[2]**3if i == sum:print("%d \t " %i, end=" ")
6.运行结果
在中运行程序 , 结果如图3.7所示 。
7.问题拓展
本题程序采用的是从低位到高位的顺序进行分离 。下面将从高位
到低位顺序进行拆分的程序段给出 , 供读者参考 。
#!/usr/bin/python3# -*- coding: utf-8 -*-# @author : liuhefei# @desc: 阿姆斯特朗数if __name__ == "__main__":a = [0, 0, 0] # 列表a用来存储被拆分的数的个位、十位和百位print("1000以内的阿姆斯特朗数:")for i in range(2, 1000):# 按从高位到低位的顺序拆分数t = 0k = 1000while k >= 10:a[t] = (i % k) // (k // 10)k = k // 10t += 1sum = a[0]**3 + a[1]**3 + a[2]**3if i == sum: # 判断是否为阿姆斯特朗数print("%d \t" %i, end=" ")