前言
不知不觉,已经有3天多没有写博客了,意味着我又很多天没有码代码了……学编程最重要的一点,就是Keep Coding Everyday。我现在有深刻体会了!今天要写的程序非常简单,而我却花了很长时间去写,说明熟练度远远不够……是的,现在的生活很忙碌了,很多要兼顾,但自我提升,不都是各种时间协调,安排出时间来的吗?现在哪有只需要学习其他都不用考虑的生活啊,当然, 有也一定很无聊。希望接下来大家多多监督,这个博客,我肯定是不会放的,即使再忙!
系列说明
接下来一段时间,都会是用编程求解数学问题,这些问题相对简单,很适合练手。
问题
求解10000以内的所有完数。
名词解释
完数,就是它的所有因子,加起来,等于它这个数。如 6 = 1 + 2 + 3 6 = 1+2+3 6=1+2+3。
编程思路
- 求解一个数的所有因子
- 判断这些因子相加是否等于这个数本身
实现代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2019-04-03 10:32:53
# @Author : Promise (promise@mail.ustc.edu.cn)
# @Link : ${link}
# @Version : $Id$
def findPefectNum():
factorList = [] # 理论上因子个数是未定的
perfectNumberConut = 0
for i in range(2, 10000):
s = i # 用于储存检验的这个数
count = 0 # 计数的变量
for j in range(1, i//2+1):
if i % j == 0:
factorList.append(j) # 采用append(),不用考虑因素个数问题
s -= j
count += 1
if s < 0:
break # 当s小于零,说明这个整数不可能是完数了
if s == 0: # 说明找到完数了
perfectNumberConut += 1
print('第', perfectNumberConut, '个完数:', i)
findPefectNum()
运行结果
代码分析
- 第二个for循环里面,如果 s < 0 s < 0 s<0了,说明这个数肯定不是完数,跳出循环,提高效率
- 同样是第二个for, j 的终点设为 i 的一半,是因为任何数,都不会有大于自身一半的因数(这个数自身除外,想想为什么,你会发现很有趣!)
经验总结
出师不利,这个算法用了错误的学习方法,我先看了教材的解法,然后希望跟之前写排序算法一样,默写出来……但这样其实反而拖慢我自己的速度……因为这种简单问题,照着编程思路,很快就可以写出来的,或许一开始效率不行,但之后再调整就好了。
**另外!!!**教材再次有出错的代码,跟着它打,我也跟着错了……
多余的分析
下图的代码,是用C++写的,在一开始,程序假设了因子最多30个,所以有
long p[30];
但实际上,在运行过程中,有些数的因子数不止有30个,所以会报错(索引溢出)。
于是,在上面我自己的程序,我改为不确定数组个数了。理论上,这会拖慢运行速度,但相比莫名的程序出错,我觉得这个代价可以接受。
最后再吐槽一句:不严谨的教材害死人……