【问题标题】:Python List vs Java Array efficiency [duplicate]Python List vs Java Array效率[重复]
【发布时间】:2015-01-04 19:34:16
【问题描述】:

我来自 Java,正在尝试学习 Python。我首先在 Java 中实现了 Sieve of Eratosthenes 算法,然后在 Python 中实现。我的 Java 实现运行得相当快,我可以在大约 25 秒内找到所有低于 10 亿的素数。我的 Python 实现可能需要大约 2 个小时才能完成相同的操作。

我在这里包含了这两种实现。我的问题是:

  1. 为什么 Python 实现这么慢? (我知道我做错了什么)
  2. 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


【解决方案1】:

我不是 Python 方面的专家,但我会尽力给你一个体面的答案。

首先,Python 是一种脚本语言,这使得它比任何编译语言(例如 Java)都慢。例如,无法对循环执行许多优化,并且对于非常大的循环,它可能会减慢您的代码。然而,我知道在 Python 的某些实现中也存在预编译,并且执行的实际上是字节码,就像在 Java 中一样,所以可能差异并不那么显着。

然后,我认为您可以通过从一开始就为您的列表分配正确的大小来加快您的 Python 版本(我相信 Python 列表实际上是数组):

 primes = [True] * limit

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    相关资源
    最近更新 更多