我正在Project Euler处理一个问题;我在SO中找到了question。问题和接受的答案说明了;
n = 600851475143
i = 2
while i * i < n:
while n%i == 0:
n = n / i
i = i + 1
print (n)
这太棒了。我仍然无法理解这个过程如何如此之快,并且可以在0.00001秒内找到600亿的最大素数因子。我尝试了大量的方法和代码,过程耗时超过1小时..
有人能解释一下这些代码的逻辑以及为什么它超快吗?是while
循环在Python中有一个特殊的地方吗?
答案 0 :(得分:4)
fundamental theorem of arithmetic表示每个大于1的整数都可以表示为素数的乘积。例如,数字2100可以表示如下:
2 x 2 x 3 x 5 x 5 x 7
我已经安排了它,所以最大的素数因子在右边,在这种情况下7.此算法正在做的是从2开始并除以n
(即&#34;删除&#34 ;那个因素)直到没有更多要删除(模0步检查它在分割之前是否可以完全整除。)
因此,根据代码,我们会i
= 2且n
= 2100,或
2 x 2 x 3 x 5 x 5 x 7
2100可以被2整除(2100 % 2 == 0
),也因为我们在上面的分解中看到了2。所以除以2得到1050,或
2 x 3 x 5 x 5 x 7
再继续除以2,你得到一个不再被2整除的数字,即525,或
3 x 5 x 5 x 7
然后我们将i
增加到3并继续。看看到底我们将留下最高的素因子?
第一个while循环i * i < n
(真的应该是i * i <= n
)的原因是因为
如果一个除数或一个数的因子(除了一个完美的平方)大于它的平方根,那么另一个因子将小于它的平方根。因此,不需要考虑大于 n 的平方根的所有素数倍数。
来自:http://britton.disted.camosun.bc.ca/jberatosthenes.htm
因此,如果i
大于n
的平方根,则意味着所有剩余因素都会产生&#34;对#34;我们已经发现,低于n
的平方根。使用的检查i * i <= n
是等效的,但比进行平方根计算更快。
这是如此之快以及其他蛮力方法如此之慢的原因是因为这会将每个步骤中的数字减少,这会以指数方式减少需要完成的步骤数。
要看到这一点,600851475143的素数分解是
71 x 839 x 1471 x 6857
如果您将代码修改为:
n = 600851475143
i = 2
while i * i <= n:
while n%i == 0:
print "Dividing by %d" % i
n = n / i
i = i + 1
if n > 1:
print n
你会看到:
>>>
Dividing by 71
Dividing by 839
Dividing by 1471
6857
向您展示这正是它的工作方式。