python3 题解(6)完全数

完全数

【问题】如果一个正整数的所有因子的和是自身的2倍(也可以描述为:除了自身之外的因子之和正好等于自身),则称之为完全数。
比如: 6, 28 就是前2个完全数。请找出10000以内的所有完全数。

这个定义很容易理解,解法也很明显:从1开始向上搜索,每遇到一个因子,就累加起来。最后看看是不是符合条件。

def is_wan_quan(n):
	sum = 0
	for i in range(1,n):
		if n % i == 0: sum += i
	return sum == n

if __name__ == '__main__':
	for i in range(10000):
		if is_wan_quan(i): print(i)

稍微有点遗憾的是运行速度较慢。
看看有没可以优化的地方。

因子总成对出现的。如果 p 是 n 的因子,必然 q = n // p 也是 n 的因子。
我们只要找到了一半数目的因子,另一半可以计算出来。

所以,不需要从 1 搜索到 n, 只要到 大约 n \sqrt{n} n 就够了。

下面的代码就利用这个原理,速度大为提高。

import math

def is_wan_quan(n):
	sum = 0
	k = round(math.sqrt(n))
	if k * k <= n:  k +=1

	for i in range(1, k):
		if n % i == 0: 
			sum += i
			if(n//i != i): sum += n // i

	return sum == 2 * n

if __name__ == '__main__':
	for i in range(1,10000):
		if is_wan_quan(i):
			print(i)

这里对开方的处理要小心。因为计算表示小数时是不精确的。一个正好可以开方的数字,其结果也可能会有点误差。这里开方出来的数字再平方回去就是为了消除这种误差的影响。

如果对这个问题不理会,甩锅给 python,直接让它比较整数和浮点数。

import math

def is_wan_quan(n):
	t = math.sqrt(n)
	sum = 0
	i = 1
	while i<=t:
		if n % i == 0: 
			j = n // i
			sum += i + (j if j > i else 0)
		i += 1
	return sum == 2 * n

if __name__ == '__main__':
	for i in range(1,10000):
		if is_wan_quan(i): print(i)

似乎对这个问题也没多大影响。
但浮点数不精确的这个坑是真实存在,看下面的例子:

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)

结果居然是 False !!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值