【发布时间】:2015-01-04 19:34:16
【问题描述】:
我来自 Java,正在尝试学习 Python。我首先在 Java 中实现了 Sieve of Eratosthenes 算法,然后在 Python 中实现。我的 Java 实现运行得相当快,我可以在大约 25 秒内找到所有低于 10 亿的素数。我的 Python 实现可能需要大约 2 个小时才能完成相同的操作。
我在这里包含了这两种实现。我的问题是:
- 为什么 Python 实现这么慢? (我知道我做错了什么)
- Python 是否可以像 Java 一样快地做到这一点?
我假设缓慢的中心是在 Python 实现中使用列表,但我对 Python 太陌生,不知道如何解决这个问题。
JAVA:
/**
* Creates a boolean array of a specified size with true values at prime indices and
* false values at composite indices.
*/
private static boolean[] sieve(int size){
boolean[] array = new boolean[size];
//Assume all numbers greater than 1 are prime//
for(int i = 2; i < array.length; i++){
array[i] = true;
}
//Execute Sieve of Eratosthenes algorithm//
for(int p = 2; p < size; p = nextPrimeInArray(array, p)){
for(int i = p + p; i < size; i += p){
array[i] = false; // i.e., mark as composite
}
}
return array;
}
/**
* Finds the next index in the array that is not marked composite
*/
public static int nextPrimeInArray(boolean[] array, int p){
do{
p++;
}while(p < array.length && !array[p]);
return p;
}
Python:
def getPrimeList(limit):
"""returns a list of True/False values, where list[i] is True if i is prime and False otherwise"""
primes = []
# Initially assume all numbers in the list are prime
for i in range(limit):
primes.append(True)
# Set 0 and 1 to False
primes[0] = False
primes[1] = False
for p in range(2, limit):
for i in range(p + p, limit, p):
primes[i] = False
p = nextPrimeInList(primes, p)
return primes
def nextPrimeInList(list, p):
"""Helper method for getPrimeList that finds the next index in list not marked composite"""
p += 1
while p < len(list) and not list[p]:
p += 1
return p
【问题讨论】:
-
尝试在 PyPy 上运行,看看它是否变得更快
-
这是一个相当复杂的问题,需要很长时间才能解释清楚,但基本上阅读了解释型和编译型语言运行时,看看为什么总的来说编译速度更快。
-
这是 Python 2 吗?您在这里没有利用 Python 众所周知的习语,例如:
primes = [True]*limit将会非常快。话虽如此,这个问题属于 Codereview.SE IMO。 -
Java 非常快,这要归功于 JIT 编译器。长时间运行的代码/循环被翻译为本机代码并优化。为了测试,请尝试使用 -Djava.compile=NONE 禁用 Java 的 JIT。
-
我建议您为此使用 NumPy,因为 Python 中的所有内容都是一个对象,因此即使是整数、布尔值也会占用大量内存。相比之下,
primesfrom2to在我的系统上只用了 7 秒,而基于纯 Python 的rwh_primes2需要 27 秒。
标签: java python sieve-of-eratosthenes