【问题标题】:python sum of primespython素数之和
【发布时间】:2013-06-20 19:57:39
【问题描述】:

我想做一个python程序来生成一个数的质数之和,但是程序没有给出正确的结果,请告诉我为什么。

b=1
#generates a list of numbers.
while b<100:
    b=b+1
    x = 0.0
    a = 0
    d = 0
    #generates a list of numbers less than b. 
    while x<b:
        x=x+1
        #this will check for divisors. 
        if (b/x)-int(b/x) == 0.0:
            a=a+1
        if a==2:
            #if it finds a prime it will add it.
            d=d+b
print d 

我让它成功生成了一个素数列表,但我无法添加要添加的素数。

这是我用来生成素数列表的代码。

b=1
while b<1000:
    b=b+1
    n = b
    x = 0.0
    a = 0
    while x<n:
        x=x+1
        if (n/x)-int(n/x) == 0.0:
            a=a+1
    if a==2:
        print b

【问题讨论】:

  • 你有你写的代码吗?
  • 什么意思?代码在上面,或者你的意思是生成素数列表的代码。
  • @kyle_k 我的意思是你有汇总列表的代码,但我在下面添加了要做什么。
  • 你能更具体地谈谈你的目标吗?一个数的素数之和 = foo(15) = 3+5 = 8?
  • 不应该检查a==2 到内部while 之外吗?

标签: python sum primes


【解决方案1】:

您的d 变量在您的外循环的每次迭代中都会被重置。将初始化移出该循环。

此外,a == 2 检查应该只在外循环的每次迭代中发生一次。将其移出内循环。

b=1
d = 0
#generates a list of numbers.
while b<100:
    b=b+1
    x = 0.0
    a = 0
    #generates a list of numbers less than b. 
    while x<b:
        x=x+1
        #this will check for divisors. 
        if (b/x)-int(b/x) == 0.0:
            a=a+1
    if a==2:
        #if it finds a prime it will add it.
        d=d+b
print d 

结果:

1060

在我们处理它的同时,让我们尝试清理代码以使其更易于理解。您可以将内部循环移动到自己的函数中,以便读者更清楚地了解其用途:

def is_prime(b):
    x = 0.0
    a = 0
    while x<b:
        x=x+1
        #this will check for divisors. 
        if (b/x)-int(b/x) == 0.0:
            a=a+1
    if a==2:
        return True
    else:
        return False

b=1
d=0
#generates a list of numbers.
while b<100:
    b=b+1
    if is_prime(b):
        d=d+b
print d

使用描述它们所代表的变量名称也很有用:

def is_prime(number):
    candidate_factor = 0
    amount_of_factors = 0
    while candidate_factor<number:
        #A += B is equivalent to A = A + B
        candidate_factor += 1
        #A little easier way of testing whether one number divides another evenly
        if number % candidate_factor == 0:
            amount_of_factors += 1
    if amount_of_factors == 2:
        return True
    else:
        return False

number=1
prime_total=0
#generates a list of numbers.
while number<100:
    number += 1
    if is_prime(number):
        prime_total += number
print prime_total

for 循环比增加计数器的while 循环更符合规范:

def is_prime(number):
    amount_of_factors = 0
    for candidate_factor in range(1, number+1):
        if number % candidate_factor == 0:
            amount_of_factors += 1
    if amount_of_factors == 2:
        return True
    else:
        return False

prime_total=0
#generates a list of numbers.
for number in range(2, 101):
    if is_prime(number):
        prime_total += number
print prime_total

如果您觉得大胆,可以使用列表推导来减少您使用的循环数量:

def is_prime(number):
    factors = [candidate_factor for candidate_factor in range(1, number+1) if number % candidate_factor == 0]
    return len(factors) == 2

#generates a list of numbers.
primes = [number for number in range(2, 101) if is_prime(number)]
prime_total = sum(primes)
print prime_total

【讨论】:

  • +1 这是您问题的实际答案。我觉得我应该提一下,如果您要将此代码用于大量 b,您需要 1) 只检查平方根或 2) 更好的是,使用筛子
  • 1 的素数之和真的是 1060 吗?另外,据我所知,20 的质数之和是 2+2+5=9 而不是 983。我希望我可以使用这段代码,但它不像我例外的那样工作!
  • @AdriansNetlis,此代码查找小于特定数字的所有素数之和,并且您似乎想要找到一个数字的所有素数之和。前任。当你在我的代码中用 20 替换 101 时,你会得到 2+3+5+7+11+13+17+19 = 77。不确定你从哪里得到 983。
  • 但是如何让它从数字中得到所有的质因数,而不是把它们相加呢?但是你从哪里得到 101?我只看到 b = 1 和 d = 0。b 不是要替换的数字吗?
【解决方案2】:

Kevin 正确回答了您提出的问题。请允许我回答您没有问但应该有的问题:计算小于n的素数之和的最佳方法是什么。答案是用筛子:

def sumPrimes(n):
    sum = 0
    sieve = [True] * (n+1)
    for p in range(2, n):
        if sieve[p]:
            sum += p
            for i in range(p*p, n, p):
                sieve[i] = False
    return sum

这段代码实现了埃拉托色尼筛法,在进行过程中对素数求和。它的工作原理是重复选择最小的未交叉数(上面代码中的p,当sieve[p]True 时选择),然后删除它的所有倍数(i em> 在上面的代码中,它从它的平方开始以 p 递增来计算 p 的倍数(因为所有较小的组合都已经被划掉了)。该函数的一个示例使用是print sumPrimes(100),它打印1060,这是正确的答案。

请注意,Roland 的回答并未实施埃拉托色尼筛法,尽管他声称确实如此;使用模函数是 Roland 的答案使用试除法的赠品,不是 Eratosthenes 的筛子。

如果您对使用素数进行编程感兴趣,我在我的博客中谦虚地推荐essay

【讨论】:

  • 谢谢,我一直想使用 Eratosthenes 筛子已经有一段时间了,但所有其他示例对我来说都没有意义,这个我能理解,谢谢。
【解决方案3】:

如果您这样做是为了学习 python,那么可以使用更简洁(>> 不易出错)的方式来执行此操作。根据您的问题我假设您正在尝试将以下所有素数相加,包括 100

sum=0
limit=100
for n in range(2,limit+1):
  if all(n % i for i in range(2, n)):
    sum += n
print sum

打印1060

【讨论】:

  • 如果你想帮助他们学习 Python,解释更深奥的 Python 主义会很有帮助,比如你的列表理解和你使用的函数。
  • 点了,但我确信我的代码具有足够的可读性并提供足够的提示,让 Google 完成其余的教学,如果学习确实是 OP 的目标。
【解决方案4】:

列表推导是 Python 中的一个强大工具。将它们视为类固醇中的 for 循环。 :-) 您可以使用它们来实现试除法,这是一种查找素数的简单方法。

它是这样工作的:

In [4]: sum(prime_list(100))
Out[4]: 1061

prime_list 函数:

def prime_list(num):
    """Returns a list of all prime numbers up to and including num.
    Based on trial division.

    :num: highest number to test
    :returns: a list of primes up to num

    """
    if num < 3:
        raise ValueError('this function only accepts arguments > 2')
    candidates = range(3, num+1, 2) # (a)
    L = [c for c in candidates if all(c % p != 0 for p in range(3, c, 2))] #(b)
    return [1, 2] + L

现在解释一下。除 2 外,所有素数都是奇数。所以从 3 到num(本例中为 100)的所有奇数都是素数的候选者。让我们生成一个在 (a) 处完成的列表:

In [5]: num = 100

In [6]: range(3, num+1, 2)
Out[6]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

要使奇数 c 成为质数,必须确保 c 对所有先前的奇数 p 取模后必须为非零。假设c 是 25。

In [7]: c = 25

那么p 在:

In [8]: range(3, c, 2)
Out[8]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]

现在检查c 取模p

In [9]: [c % p != 0 for p in range(3, c, 2)]
Out[9]: [True, False, True, True, True, True, True, True, True, True, True]

我们知道 25 % 5 == 0,所以列表中的第二项是False。但是,要使一个数字成为素数,列表中的所有项目都必须为真:

In [10]: all(c % p != 0 for p in range(3, c, 2))
Out[10]: False

所以 25 不是素数。

让我们再试一次c 是 41:

In [11]: c = 41

In [12]: range(3, c, 2)
Out[12]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39]

In [13]: [c % p != 0 for p in range(3, c, 2)]
Out[13]: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]

In [14]: all(c % p != 0 for p in range(3, c, 2))
Out[14]: True

确实,41 是质数。

所以 prime_list 返回一个素数列表:

In [15]: prime_list(100)
Out[15]: [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

总而言之,我们只需使用sum() 函数:

In [16]: sum(prime_list(100))
Out[16]: 1061

编辑:基于 cmets,我尝试了 WillNess 建议的改进和使用集合的真正筛子:

def prime_list(num):
    if num < 3:
        raise ValueError('this function only accepts arguments > 2')
    candidates = range(3, num+1, 2)
    L = [c for c in candidates if all(c % p != 0 for p in range(3, c, 2))]
    return [1, 2] + L

def prime_list2(num):
    if num < 3:
        raise ValueError('this function only accepts arguments > 2')
    candidates = range(3, num+1, 2)
    L = [c for c in candidates if all(c % p != 0 for p in
         range(3, int(math.sqrt(c))+1, 2))]
    return [1, 2] + L

def prime_list3(num):
    candidates = set(range(3, num+1, 2))
    results = [1, 2]
    while candidates:
        t = list(candidates)[0]
        results.append(t)
        candidates -= set(range(t, num+1, t))
    return results

num=100 的一些时间安排:

In [8]: %timeit prime_list(100)
1000 loops, best of 3: 180 us per loop

In [9]: %timeit prime_list2(100)
1000 loops, best of 3: 192 us per loop

In [10]: %timeit prime_list3(100)
10000 loops, best of 3: 83.9 us per loop

还有num=1000

In [11]: %timeit prime_list(1000)
100 loops, best of 3: 8.05 ms per loop

In [12]: %timeit prime_list2(1000)
100 loops, best of 3: 2.43 ms per loop

In [13]: %timeit prime_list3(1000)
1000 loops, best of 3: 1.26 ms per loop

num = 5000:

In [14]: %timeit prime_list(5000)
1 loops, best of 3: 166 ms per loop

In [15]: %timeit prime_list2(5000)
100 loops, best of 3: 11.1 ms per loop

In [16]: %timeit prime_list3(5000)
100 loops, best of 3: 15.3 ms per loop

最后是num=50000

In [18]: %timeit prime_list3(50000)
1 loops, best of 3: 1.49 s per loop

In [19]: %timeit prime_list2(50000)
1 loops, best of 3: 170 ms per loop

【讨论】:

  • if all(c % p != 0 for p in range(3, sqrt(c)+1, 2)) 获得的速度提升。 :) 如果sqrt 计算占用太多时间,请将其重写为一个简单的循环,并检查p*p &lt;= c(可能更快)。
  • @WillNess:很有趣。它工作正常(至少高达 10000 :-)),但我还没有看到为什么?
  • 但是速度增益是多少?现在关于“为什么”:如果a*b == na &gt;= sqrt(n) 那么肯定是b =&lt; sqrt(n),所以你会在a 之前遇到it。其中之一肯定是&lt;= sqrt(n),如果有任何a,b 这样n == a*b。因此,如果我们到达sqrt,但仍然没有找到这样的数字, - 这是一个素数
  • @WillNess:我添加了一些时间
  • 我的解释呢? :) -- 你的新代码:如果 prime_list3(n) 是 Erat 筛的最佳 impl'n,它会比 prime_list2(n) 更快,这只是一个次优的试验部门。当t 高于sqrt(num) 时,您可以停止减组。此时候选中剩下的所有数字都是素数。 但是这无济于事:在每次迭代中将集合变成列表(以找到它的最小元素,对吗?)无可救药地破坏了整体复杂性。您需要分别生成低于 sqrt(num) 的素数,以进行集合减法。你能用筛法吗??
【解决方案5】:

只需使用您用于生成列表的代码对列表求和:

d = sum(d)
print d

【讨论】:

  • 你指的是什么列表? OP 的代码中没有任何列表。 d 是一个整数。
  • "我让它成功地生成了一个素数列表。"他没有发布的代码,但说他实现了。
【解决方案6】:
def sum_of_prime(num):
        if num < 2:
            return 'Please enter values greater than 2'
        if num == 2:
                return 2
        sum = 0
        for j in range(2,num):
                for i in range(2,j):
                        if (j % i) == 0:
                                break
                else:
                        print j
                        sum = sum + j
        return sum
num = int(raw_input())
result = sum_of_prime(num)
print result

【讨论】:

  • 你的电话sum_of_prime(3)不会也返回2吗?这与为 num=2 返回 2 不一致。效率如何?您的empirical orders of growth 与其他答案相比如何?
猜你喜欢
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多