【问题标题】:Count the number of prime numbers less than a non-negative number, n in Python计算小于非负数的素数个数,Python 中的 n
【发布时间】:2016-01-23 17:57:48
【问题描述】:

我正在解决来自leetcode 的编码问题,我们应该计算小于非负数 n 的素数的数量。

这是我的解决方案:

class Solution(object):

    def isPrime(self, Number):
        return 2 in [Number, 2**Number % Number]

    def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        count_prime = 0
        prime_range = filter(lambda x: x % 2 != 0 and x % 3 != 0 and x % 5 != 0, xrange(n))

        for i in prime_range:
            if self.isPrime(i):
                count_prime += 1

        return count_prime

print Solution().countPrimes(499979)

虽然这适用于较小的数字,但较大的数字会花费大量时间,而且我不确定哪个部分在我的程序中消耗更多时间?这里我只测试大于 100 的数字。

谁能帮我找出哪个部分需要更多时间

【问题讨论】:

  • 顺便说一句,341 是最小的费马伪素数。它是复合的最小正数,但您的 isPrime 函数返回 True
  • 您可能想查看 Python 的 pow function 的 3 参数形式。并阅读伪素数、强伪素数、卡迈克尔数和埃拉托色尼筛法。
  • 1387, 1729, 2047, 2701, 2821, 3277, 4033, 4369, 4681, 5461, 6601, 7957, 8321, 8911 是您的 isPrime 的更多误报
  • 请注意,在 Eratosthenes 的筛子实现中,您根本不需要 isPrime:将 if self.isPrime(i): 替换为 if total_prime[i]:(并删除 total_prime[i] = True 行:这是多余的)。跨度>
  • 请不要在帖子中添加您的答案。考虑创建一个新答案并解释您在该答案中执行的步骤。在这种情况下,我已经回滚了编辑。下次小心点。问候

标签: python math time-complexity primes


【解决方案1】:

谁能帮我找出哪个部分需要更多时间

为什么可以Python可以。简而言之,Python 与cProfile 捆绑在一起,这是一个用于 Python 代码的分析器。在其下运行您的模块会产生以下统计信息:

jim@jim: python -m cProfile tt.py 
673
         6311 function calls in 0.016 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.016    0.016 tt.py:1(<module>)
        1    0.000    0.000    0.000    0.000 tt.py:1(Solution)
     4979    0.002    0.000    0.002    0.000 tt.py:12(<lambda>)
     1327    0.013    0.000    0.013    0.000 tt.py:3(isPrime)
        1    0.000    0.000    0.016    0.016 tt.py:6(countPrimes)
        1    0.001    0.001    0.003    0.003 {filter}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

所有这些列在哪里are described in the documentation。所以,如你所见,大部分时间实际上都花在了函数isPrime

1327    0.013    0.000    0.013    0.000 tt.py:3(isPrime)

1327 调用总共花费了0.013/0.016 总时间。是的,这就是问题所在。

现在,在您发现瓶颈在哪里之后,您可以尝试寻找优化方法。 在大多数情况下,您只需使用更高效的算法和合适的数据结构即可获得更好的性能。

如果您想更快更快,请考虑查看CythonNumba 之类的内容。如果那些不削减它写一个纯粹的C 扩展,它可能会运行得更快一点。如果还是不行,那就放弃吧,因为你对任何事情都不满意。

【讨论】:

  • 谢谢!这2 in [Number, 2**Number % Number] 不应该花费固定的时间吗?知道为什么这个函数需要更多时间。
  • @python:值2**Number 的位数与Number 成正比(实际上,等于以2 为底的Number+1),因此很快就不适合任何底层固定Python 使用的 -width 类型。结果是% 操作所花费的时间与Number 大致成正比。
  • 确实,在这种情况下,列表文字内的计算会影响您。这应该会让您质疑解决此问题的这种特殊方式,而是尝试找到更有效的算法。
【解决方案2】:

您看过埃拉托色尼筛吗?它是寻找素数的经典算法:

埃拉托色尼筛法是一种简单的算法,可以找出不超过给定整数的素数。实现这个算法,唯一允许的优化是外循环可以在极限的平方根处停止,而内循环可以从刚刚找到的素数的平方开始。这尤其意味着您不应该通过使用预先计算的轮子进行优化,即不要假设您只需要删除奇数(基于 2 的轮子)、等于 1 或 5 模 6 的数字(基于 2 的轮子和3),或基于低素数的类似轮子。 http://rosettacode.org/wiki/Sieve_of_Eratosthenes

Sieve of Eratosthenes - Finding Primes Python

【讨论】:

  • 谢谢!但是我的程序有什么问题?它应该运行得足够快以计算所有小于n 的素数,即使是更大的数字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
相关资源
最近更新 更多