打开与程序相关的文件是否也会停止程序?

时间:2013-04-26 22:48:36

标签: python-2.7 perfect-numbers

我有这个程序应该搜索完美的数字。 (如果除以X的所有数字之和除以2等于X,则X是一个完美的数字) sum / 2 = x

现在已经找到了前四个,这在古希腊是众所周知的,所以它并不是真的很棒。

下一个应该是33550336。

我知道这是一个很大的数字,但程序已经持续了大约50分钟,但仍然没有找到33550336.

是不是因为我打开了.txt文件,我在程序运行时存储了所有完美的数字,或者是因为我没有足够快的PC运行它*,或者因为我使用的是Python ?

*注意:同样的PC在10分钟内分解了50万(同时还运行了完美的数字程序和带有3个YouTube标签的谷歌浏览器),也使用了Python。

以下是该计划的代码:

i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
    sum = 0
for x in range(1, i+1):
    if i%x == 0:
        sum += x
if sum / 2 == i:
    a = open("perfect.txt", 'a')
    a.write(str(i) + "\n")
    a.close()
i += 1

3 个答案:

答案 0 :(得分:5)

  

下一个应该是33550336。

你的代码(我修改了缩进,使其原则上符合你的要求):

i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
    sum = 0
    for x in range(1, i+1):
        if i%x == 0:
            sum += x
    if sum / 2 == i:
        a = open("perfect.txt", 'a')
        a.write(str(i) + "\n")
        a.close()
    i += 1

执行i分区以找到i的除数。

所以要找到最高n的完美数字,它确实

2 + 3 + 4 + ... + (n-1) + n = n*(n+1)/2 - 1

for循环中的分割。

现在,对于n = 33550336,那将是

Prelude> 33550336 * (33550336 + 1) `quot` 2 - 1
562812539631615

大约5.6 * 10 14 分部。

假设您的CPU每秒可以进行10次 9 分割(很可能不会,10 8 在我的经验中是一个更好的估计,但即便如此机器int在C),大约需要560,000秒。一天有86400秒,所以这将是大约六天半(超过两个月,10 8 估计)。

你的算法太慢,无法在合理的时间内达到。

如果你不想使用数论(即使完美的数字有一个非常简单的结构,如果有任何奇数的完美数字,那些必然是巨大的),你仍然可以做得更好,只划分为平方根找到除数,

i = 2
a = open("perfect.txt", 'w')
a.close()
while True:
    sum = 1
    root = int(i**0.5)
    for x in range(2, root+1):
        if i%x == 0:
            sum += x + i/x
    if i == root*root:
        sum -= x        # if i is a square, we have counted the square root twice
    if sum == i:
        a = open("perfect.txt", 'a')
        a.write(str(i) + "\n")
        a.close()
    i += 1

只需要大约1.3 * 10 11 分区,并且应该在几个小时内找到第五个完整数字。

不使用显式公式甚至是完美的数字(2^(p-1) * (2^p - 1)为素数p,使2^p - 1为素数),你可以通过找到{的素数因子化来加速它。 {1}}并从中计算除数和。这将使所有复合数字的测试更快,对大多数人来说更快,

i

在我的机器上估计需要40分钟。

估计不错:

def factorisation(n):
    facts = []
    multiplicity = 0
    while n%2 == 0:
        multiplicity += 1
        n = n // 2
    if multiplicity > 0:
        facts.append((2,multiplicity))
    d = 3
    while d*d <= n:
        if n % d == 0:
            multiplicity = 0
            while n % d == 0:
                multiplicity += 1
                n = n // d
            facts.append((d,multiplicity))
        d += 2
    if n > 1:
        facts.append((n,1))
    return facts

def divisorSum(n):
    f = factorisation(n)
    sum = 1
    for (p,e) in f:
        sum *= (p**(e+1) - 1)/(p-1)
    return sum

def isPerfect(n):
    return divisorSum(n) == 2*n

i = 2
count = 0
out = 10000
while count < 5:
    if isPerfect(i):
        print i
        count += 1
    if i == out:
        print "At",i
        out *= 5
    i += 1

答案 1 :(得分:0)

很难尝试并推断出这种情况发生的原因。我建议您在调试器下运行程序并手动测试几次迭代以检查代码是否真的正确(我知道您已经计算了4个数字但仍然)。或者,最好在python profiler下运行你的程序,看看它是否没有意外地阻塞锁或其他东西。

答案 2 :(得分:0)

这可能,但不太可能这是与您在运行时打开文件相关的问题。如果这是一个问题,可能会有一些错误消息和/或程序关闭/崩溃。

我会编辑程序,每隔一段时间就将一个日志类型输出写入文件。例如,每次处理的目标编号是1百万的偶数倍时,请将日期时间和当前编号以及最后成功编号写入(open-append-close)到日志文件中。

然后您可以偶尔 Type 该文件来衡量进度。