【问题标题】:Does opening a file related to the program also stop the program?打开与程序相关的文件是否也会停止程序?
【发布时间】:2014-06-18 21:11:08
【问题描述】:

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

现在它已经找到了前四个,它们在古希腊就为人所知,所以它并不是什么了不起的东西。

下一个应该是 33550336。

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

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

*注意:这台 PC 在 10 分钟内分解了 500 000(同时还运行完美数字程序和带有 3 个 YouTube 标签的 Google Chrome),同样使用 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

【问题讨论】:

  • 您的问题与您的问题没有任何关系。但是,没有人可以在不看代码的情况下帮助您。
  • 你是什么意思?我打开了存储所有完美数字的文件,我想知道该应用程序找不到其他任何东西的原因。我不得不解释什么是完美数字,不是每个人都知道什么是完美数字。我已经发布了一些代码来帮助你。

标签: python-2.7 perfect-numbers


【解决方案1】:

下一个应该是 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 * 1014 个分区。

假设您的 CPU 每秒可以进行 109 分区(很可能不能,根据我的经验,108 是一个更好的估计,但即便如此机器 ints 在 C 中),这将需要大约 560,000 秒。一天有 86400 秒,因此大约是六天半(按 108 估计超过两个月)。

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

如果你不想使用数论(即使是完美的数字也有一个非常简单的结构,如果有奇完美的数字,它们一定是巨大的),你仍然可以通过只除以做得更好求除数的平方根,

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 * 1011 个除法,并且应该在几个小时内找到第五个完美数字。

不求助于偶完美数的显式公式(2^(p-1) * (2^p - 1) 用于素数 p 使得 2^p - 1 是素数),您可以通过找到 i 的素数分解并计算除数来加快速度总和。这将使所有合数的测试更快,并且对大多数人来说更快,

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

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

不错的估计:

$ time python fastperf.py 
6
28
496
8128
33550336

real    36m4.595s
user    36m2.001s
sys     0m0.453s

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我很高兴地说你是对的,但是由于我对编程比较陌生,尤其是在 Python 中编程,所以我完全不知道你在说什么。 'blocked on a lock' 到底是什么意思?
    • @user2154354 - Lord 正在谈论您的程序可能是 stuck 等待访问文件或其他资源的可能性 locked 由另一个程序或进程。
    【解决方案3】:

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

    我会编辑程序以每隔一段时间将日志类型的输出写入文件。例如,每次您处理的目标数字是 1 百万的偶数倍时,将日期时间和当前数字以及最后成功数字写入(打开-追加-关闭)日志文件。

    然后您可以不时地Type该文件来衡量进度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      相关资源
      最近更新 更多