范围是[10 ^ 9-10 ^ 6 tiill 10 ^ 9]。我已经尝试了所有我能找到并想到的东西 - 用Eratosthenes的Sieve预先计算并预先检查Fermat的Primality Test。但仍然无法在不到1分钟的时间内完成。
答案 0 :(得分:3)
这需要不到一秒的时间:
Python 2.7.10 (default, Jun 1 2015, 18:05:38)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def primegen(start=0): # stackoverflow.com/a/20660551
... if start <= 2: yield 2 # prime (!) the pump
... if start <= 3: yield 3 # prime (!) the pump
... ps = primegen() # sieving primes
... p = next(ps) and next(ps) # first sieving prime
... q = p * p; D = {} # initialization
... def add(m, s): # insert multiple/stride
... while m in D: m += s # find unused multiple
... D[m] = s # save multiple/stride
... while q <= start: # initialize multiples
... x = (start // p) * p # first multiple of p
... if x < start: x += p # must be >= start
... if x % 2 == 0: x += p # ... and must be odd
... add(x, p+p) # insert in sieve
... p = next(ps) # next sieving prime
... q = p * p # ... and its square
... c = max(start-2, 3) # first prime candidate
... if c % 2 == 0: c += 1 # must be odd
... while True: # generate infinite list
... c += 2 # next odd candidate
... if c in D: # c is composite
... s = D.pop(c) # fetch stride
... add(c+s, s) # add next multiple
... elif c < q: yield c # c is prime; yield it
... else: # (c == q) # add p to sieve
... add(c+p+p, p+p) # insert in sieve
... p = next(ps) # next sieving prime
... q = p * p # ... and its square
...
>>> ps = primegen(10**9-10**6)
>>> p = next(ps)
>>> result = []
>>> while p < 10**9:
... result.append(p)
... p = next(ps)
...
>>> print len(result)
47957
有关说明,请参阅 https://programmingpraxis.com/2015/07/31/incremental-sieve-of-eratosthenes/。
答案 1 :(得分:2)
因为范围只有10 ^ 6。我认为Sieve不应该表现得那么糟糕
首先生成1到10 ^ 5之间的所有素数(因为10 ^ 5平方是10 ^ 10,最大数是10 ^ 9)。
然后使用筛子如下:
创建一个大小为10 ^ 6的数组,其中索引i表示,数字10 ^ 9-10 ^ 6 + i,然后使用您的主要列表划掉所有非素数。
在使用Sieve时,当然你应该删除所有偶数,最初然后在2到10 ^ 5范围内你只有近5000个素数。总的来说它大概是10 ^ 3 * 10 ^ 6,这是10 ^ 9步,这对现代处理器来说似乎并不复杂,运行时间。
答案 2 :(得分:1)
对于我来说,在macbook pro上大约需要28秒。你想要的素数在primes
import math
def isPrime(n, primes):
limit = int(math.sqrt(n))
for i in primes:
if i > limit:
return True
if n % i == 0:
return False
return True
low_primes = [2]
for i in range(3, 10**5, 2):
if isPrime(i, low_primes):
low_primes.append(i)
primes = []
for i in range(10**9-10**6 + 1, 10**9, 2):
if isPrime(i, low_primes):
primes.append(i)
答案 3 :(得分:0)
谢谢大家!我稍后会检查你的答案,现在想办法自己怎么做 - 在那里按相反的顺序应用方法 - 首先是Fermat,然后是Eratosphen。需要2-3秒。
n = 999000000
#n = 1 # should be 78499
m = n + 1000000
def eratosphene_filter(sorted_array_of_odd):
biggest = sorted_array_of_odd[-1]
smallest = sorted_array_of_odd[0]
mapping ={i:True for i in sorted_array_of_odd}
for i in range(3, int(biggest**0.5)+1, 2):
j = nearest_from_bottom = (smallest // i) * i
while j < biggest:
if i!=j and j in mapping:
mapping[j] = False
j += i
result = []
for k,v in mapping.items():
if v:
result.append(k)
return sorted(result)
def fermat_check(x, d=2):
return pow(d, x-1, x) == 1
def primes_sieve(lower,top):
if lower < 3:
yield 1
yield 2
lower = 3
all_numbers_in_range = range(lower if lower % 2 != 0 else lower + 1, top, 2)
print(len(all_numbers_in_range))
probably_primes = list(filter(fermat_check, all_numbers_in_range))
print(len(probably_primes))
print(probably_primes[:5],'...',probably_primes[-5:])
primes_for_sure = list(eratosphene_filter(probably_primes))
print(len(primes_for_sure))
for i in primes_for_sure:
yield i
found_primes = list(primes_sieve(n, m))
print(found_primes[:5],'...',found_primes[-5:])
print(len(found_primes))