私はPython 2.7を使用しています
私が書いたエラトステネスのふるいerat()とerat2()の2つの実装のうち、erat2()には、erat2()の2回目の実行で比較的短い時間で結果が得られるという利点があります。
def erat2(num, isprime = [2]):
if num > len(isprime) + 2:
last_original = len(isprime) + 2
isprime += [num for num in xrange(last_original ,num + 1)]
for i in xrange(2,num + 1):
if isprime[i-2]:
if i <= last_original:
j = last_original//i + 1
else:
j = 2
temp = j * i
while temp <= num:
isprime[temp-2] = 0
j += 1
temp = j * i
return filter(lambda x: x != 0, isprime[:num - 1])
def erat(num):
isprime = [num for num in xrange(2,num + 1)]
for i in xrange(2,num + 1):
if isprime[i-2]:
j = 2
temp = j * i
while temp <= num:
isprime[temp-2] = 0
j += 1
temp = j * i
return filter(lambda x: x != 0, isprime)
import time
def t():
num = 100000000
i = 10
while i < num:
s = time.time()
erat2(i)
x = time.time() - s
print "%10d %10f" %(i,x),
s = time.time()
erat(i)
y = time.time() - s
print " %10f" %(y)
i *= 10
コードの 2 回目の実行で結果がはるかに高速になるという事実をサポートするために、いくつかのタイミング分析をここに示します。最初の列はテスト入力です。2列目はerat2()のタイミング、3列目はerat()のタイミングです。明らかなように、時間は 2 回目の実行で 7 分の 1 に短縮されます。
>>> t()
10 0.000000 0.000000
100 0.000000 0.000000
1000 0.000000 0.000000
10000 0.010000 0.010000
100000 0.100000 0.110000
1000000 1.231000 1.410000
10000000 13.605000 15.081000
>>> t()
10 0.000000 0.000000
100 0.000000 0.000000
1000 0.000000 0.000000
10000 0.000000 0.020000
100000 0.020000 0.140000
1000000 0.170000 1.550000
10000000 1.770000 15.752000
私が直面している問題は、このテスト入力の後にメモリ使用量が急増することです。
- メモリ消費を減らすためにできる最適化はありますか?
- このようなメモリの増加は、良い実装方法ですか?
編集:
関数erat()とerat2()の両方を少し最適化して、速度を上げました。ラムダ関数を
lambda x: x != 0
に
lambda x: x
同じ結果ですが、わずかに高速です。num = 10000000 で 1 秒速くなります。
EDIT2:
vartec と btilly の提案を使用しました。erat() を erat3() に改善しました。ここでは、タイミング チェックとともに改善された実装を示します。また、xrange 関数に式を配置すると、パフォーマンスが低下することもわかりました。パフォーマンスを向上させるために変数を追加しました。
def erat3(num):
''' Improves Sieve of eratosthenes '''
#REQUIRES MATH MODULE
if num < 2:
return []
isprime = [num for num in xrange(3,num + 1,2)]
#temp2's expression placed in xrange function => performance-loss
temp2 = int(math.sqrt(num)) + 1
for i in xrange(3, temp2 ,2):
if isprime[(i-3)/2]:
j = 3
temp = j * i
while temp <= num:
isprime[(temp-3)/2] = 0
j += 2
temp = j * i
return [2] + filter(lambda x: x, isprime)
erat() と erat3() のタイミング
>>> t()
10 0.000000 0.000000
100 0.000000 0.000000
1000 0.000000 0.000000
10000 0.010000 0.010000
100000 0.110000 0.040000
1000000 1.241000 0.530000
10000000 14.131000 6.111000