手记

[硕.Love Python] 完全数

1.题目:
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。例如,第一个完全数是6,它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。第二个完全数是28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
编程求10000以内的完全数。

2.源码:

[k for k in xrange(2, 10000) if reduce(lambda s, x: s + (k % x == 0 and (x == k / x and x or x + k / x)), xrange(1, int(k ** 0.5) + 1)) == k]

3.思路: 找出所有真因子 -> 加和 -> 比较

6人推荐
随时随地看视频
慕课网APP

热门评论

7.直接看k=28

把步骤输出出来

k:28,int(k**0.5)+1:6
k:28,s:1,x:2
(28 mod 2 == 0 and (2 == 28 / 2 or 2 + 28 / 2))
res: 16
k:28,s:17,x:3
(28 mod 3 == 0 and (3 == 28 / 3 or 3 + 28 / 3))
res: False
k:28,s:17,x:4
(28 mod 4 == 0 and (4 == 28 / 4 or 4 + 28 / 4))
res: 11
k:28,s:28,x:5
(28 mod 5 == 0 and (5 == 28 / 5 or 5 + 28 / 5))
res: False
rd: 28

发现,函数执行了4次

其中一次返回16,一次返回11,两次false

1+16+11确实等于28

但,我实在是理解不了了。


总结3个问题:

  1. 我把匿名函数拆出去了,变成命名函数,但是外面的参数k,怎么还能传到func里面?(参见2楼帖子)

  2. 老师代码中 and x是不是多余的?(参见3F)

  3. reduce(lambda s, x: s + (k % x == 0 and (x == k / x and x or x + k / x)), xrange(1, int(k ** 0.5) + 1))
    这段逻辑实在是理解不了





6.那么

(x == k / x or x + k / x)

就好理解一点点了吧?

回到刚才

k=6

(2 == 6 / 2 or 2 + 6 / 2)

返回5

5,是2和3两个约数的和

那么我之前假设的

(k % x == 0 and (x == k / x and x or x + k / x))

是求每个约数是不对的

怎么约数和直接就给算出来了,晕了



5.笨办法理解吧

k=2和k=3

xrange(1, int(k ** 0.5)返回的数组都是[1],不会触发函数,reduce直接返回1

k=4

int(4**0.5)+1是3,reduce数组[1,2]

然后,

(4 % 2 == 0 and (2 == 4 / 2 and 2 or 2 + 4 / 2))

4%2==0真

然后,2 and 2 or 4返回2

k=5

int(5**0.5)+1是3,reduce数组[1,2]

(5%2 == 0 and (2 == 5 / 2 and 2 or 2 + 5 / 2))

5%2==为false,直接短路后面的操作

k=6

int(6**0.5)+1是3,reduce数组[1,2]

(6 % 2 == 0 and (2 == 6 / 2 and 2 or 2 + 6 / 2))

6 % 2 == 0为真

and后面的()里面,2 == 6 / 2为假,and 2究竟是什么?

然后我发现,后面这个and x没用

在老师的代码把and x去掉运行一下

In [42]: [k for k in xrange(2, 10000) if reduce(lambda s, x: s + (k % x == 0 and
    ...:  (x == k / x or x + k / x)), xrange(1, int(k ** 0.5) + 1)) == k]
Out[42]: [6, 28, 496, 8128]

通过

查看全部评论