Trial Division 比 Sieve 更快进行素数测试?

Trial Division faster than Sieve for Primality Test?

我在 python 中写了两个素数测试。第一个是基于试分法,第二个是埃拉托色尼筛法。我的理解是 sieve 的时间复杂度应该比 trial 小,所以 sieve 应该渐近地更快。

可是我运行它的时候,试分就快多了。例如,当 n = 6*(10**11)is_prime(n) 只用不到一秒钟,但 is_prime_sieve(n) 几乎永远不会结束!我把筛子写错了吗?

我的代码是:

# determines if prime using trial division
def is_prime(n):
    d = {}
    u = math.floor(math.sqrt(n))
    i = 2
    # trial division: works pretty well for determining 600 billion
    while (i <= u):
        if (n % i == 0):
            return False
        i += 1
    return True

# primality test with sieve
def is_prime_sieve(n):
    # first find all prime numbers from 2 to u
    # then test them
    u = math.floor(math.sqrt(n))
    prime = {}
    lst = range(2, int(u)+1)
    for i in lst:
        j = 2
        prime[i] = True
        while (i*j <= u):
            prime[i*j] = False
            j += 1
    while (u >= 2):
        if (u not in prime) or (prime[u]):
            if (n % u == 0):
                return False
        u -= 1
    return True

对于 Erastothenes 筛法,您每次都在重新计算筛法。应该缓存筛子,以便您只生成一次。当您构建一次筛子然后执行 many 素数检查时,它会很好地工作;如果只检查一个数字,效率很低。

顺便说一句,这意味着您需要预测最高素数并生成筛 table 直至该数。

如果操作正确,is_prime_sieve 将变得简单:

def is_prime_sieve(n):
    return prime[n]

您不需要 while 循环。

筛子从 1 到 n 找到 所有 个素数。计算 one 筛比对每个数字进行试验除法要快得多。显然,如果你从1到n确定所有个素数,然后丢掉前n-1个数的所有信息,那是非常低效的。

这就像比较公共汽车和双座跑车的速度。如果你需要载五十人从 A 到 B,公共汽车要快得多。如果你只载一个乘客,你猜怎么着,跑车更快。

但即使使用传统的构建筛子的方法,仍然会发生太多的交易。 我开发了一种不除法提取质数的方法(数据管理目的除外),该方法适用于 Eratosthenes 的基本筛法。我不必设置任何上限或下限,该算法是完全开放式的。我开发了一个数据字符串,我可以从中转到计算范围内的任何地方,并提取子集范围内的所有质数。我用除法不浪费计算。