完全数
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。 它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
第一个完全数是6,第二个完全数是28,第三个完全数是496,后面的完全数还有8128、33550336等等。 截至2018年,相关研究者已经找到51个完全数。
先简单编一个程序找到前面几个完全数。
from math import ceil
n = int(input("请输入整数N:"))
for i in range(3, n):
temp = []
for j in range(1, ceil(i / 2) + 1):
if i % j == 0:
temp.append(j)
cum = 0
for k in temp:
cum += k
if i == cum:
print("{}=".format(i), end="")
for k in temp:
if k != temp[-1]:
print("{}+".format(k),end="")
else:
print("{}".format(k))
D:\Python\Python38\python.exe D:/Python/study/test23.py
请输入整数N:10000
6=1+2+3
28=1+2+4+7+14
496=1+2+4+8+16+31+62+124+248
8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064
Process finished with exit code 0
8128之后的完全数使用上述程序基本无法等待,时间太长。对上述程序进行优化,首先完全数都是三角形数,其次完全数是偶数且以6或8结束,其三,除6外,其他完全数被3、被9除余1。导入numba提速,程序如下。
from math import ceil
from numba import jit
import time
@jit(nopython=True)
def calc(n):
s, cum = 0, 0
for i in range(1, n + 1):
s += i
if s % 2 != 0:
return 0
if s > 6 and (s % 9 != 1):
return 0
if s % 10 != 6 and s % 10 != 8:
return 0
for j in range(1, ceil(s / 2) + 1):
if s % j == 0:
cum += j
if s == cum:
return s
return 0
t0 = time.time()
for m in range(2, 10000):
result = calc(m)
if result != 0:
print("{}=".format(result), end="")
for k in range(1, ceil(result / 2) + 1):
if result % k == 0:
if k != ceil(result / 2):
print("{}+".format(k), end="")
else:
print(k)
print("耗时{}s。".format(time.time() - t0))
D:\Python\Python38\python.exe D:/Python/study/test23.py
6=1+2+3
28=1+2+4+7+14
496=1+2+4+8+16+31+62+124+248
8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064
33550336=1+2+4+8+16+32+64+128+256+512+1024+2048+4096+8191+16382+32764+65528+131056+262112+524224+1048448+2096896+4193792+8387584+16775168
耗时47.46809959411621s。
Process finished with exit code 0