Ich habe einige Funktionen von unutbu getestet, ich habe sie mit hundert Millionen Zahlen berechnet
Die Gewinner sind die Funktionen, die die numpy-Bibliothek verwenden,
Hinweis: Es wäre auch interessant, einen Speicherverbrauchstest durchzuführen :)
Beispielcode
Vollständiger Code in meinem GitHub-Repository
#!/usr/bin/env python
import lib
import timeit
import sys
import math
import datetime
import prettyplotlib as ppl
import numpy as np
import matplotlib.pyplot as plt
from prettyplotlib import brewer2mpl
primenumbers_gen = [
'sieveOfEratosthenes',
'ambi_sieve',
'ambi_sieve_plain',
'sundaram3',
'sieve_wheel_30',
'primesfrom3to',
'primesfrom2to',
'rwh_primes',
'rwh_primes1',
'rwh_primes2',
]
def human_format(num):
# https://stackoverflow.com/questions/579310/formatting-long-numbers-as-strings-in-python?answertab=active#tab-top
magnitude = 0
while abs(num) >= 1000:
magnitude += 1
num /= 1000.0
# add more suffixes if you need them
return '%.2f%s' % (num, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
if __name__=='__main__':
# Vars
n = 10000000 # Anzahl der Iterationen des Generators
nbcol = 5 # Zur Zerlegung des Primzahlerzeugers
nb_benchloop = 3 # Falsch positive Werte während des Tests eliminieren (Test durchschnittliche Zeit)
datetimeformat = '%Y-%m-%d %H:%M:%S.%f'
config = 'from __main__ import n; import lib'
primenumbers_gen = {
'sieveOfEratosthenes': {'color': 'b'},
'ambi_sieve': {'color': 'b'},
'ambi_sieve_plain': {'color': 'b'},
'sundaram3': {'color': 'b'},
'sieve_wheel_30': {'color': 'b'},
# # # 'primesfrom2to': {'color': 'b'},
'primesfrom3to': {'color': 'b'},
# 'rwh_primes': {'color': 'b'},
# 'rwh_primes1': {'color': 'b'},
'rwh_primes2': {'color': 'b'},
}
# n von der Befehlszeile erhalten
if len(sys.argv)>1:
n = int(sys.argv[1])
step = int(math.ceil(n / float(nbcol)))
nbs = np.array([i * step for i in range(1, int(nbcol) + 1)])
set2 = brewer2mpl.get_map('Paired', 'qualitative', 12).mpl_colors
print datetime.datetime.now().strftime(datetimeformat)
print("Berechne Primzahlen bis %(n)s" % locals())
print("")
results = dict()
for pgen in primenumbers_gen:
results[pgen] = dict()
benchtimes = list()
for n in nbs:
t = timeit.Timer("lib.%(pgen)s(n)" % locals(), setup=config)
execute_times = t.repeat(repeat=nb_benchloop, number=1)
benchtime = np.mean(execute_times)
benchtimes.append(benchtime)
results[pgen] = {'benchtimes': np.array(benchtimes)}
fig, ax = plt.subplots(1)
plt.ylabel('Rechenzeit (in Sekunden)')
plt.xlabel('Berechnete Zahlen')
i = 0
for pgen in primenumbers_gen:
bench = results[pgen]['benchtimes']
avgs = np.divide(bench, nbs)
avg = np.average(bench, weights=nbs)
# Lineare Regression berechnen
A = np.vstack([nbs, np.ones(len(nbs))]).T
a, b = np.linalg.lstsq(A, nbs*avgs)[0]
# Plot
i += 1
#label="%(pgen)s" % locals()
#ppl.plot(nbs, nbs*avgs, label=label, lw=1, linestyle='--', color=set2[i % 12])
label="%(pgen)s avg" % locals()
ppl.plot(nbs, a * nbs + b, label=label, lw=2, color=set2[i % 12])
print datetime.datetime.now().strftime(datetimeformat)
ppl.legend(ax, loc='oben links', ncol=4)
# Ändern Sie das Beschriftung der x-Achse
ax.get_xaxis().get_major_formatter().set_scientific(False)
fig.canvas.draw()
labels = [human_format(int(item.get_text())) for item in ax.get_xticklabels()]
ax.set_xticklabels(labels)
ax = plt.gca()
plt.show()
0 Stimmen
Der Code-Schnipsel ist viel schneller, wenn Zahlen wie Zahlen = set(range(n, 2, -2)) deklariert werden. Aber kann sundaram3 nicht schlagen. Danke für die Frage.
4 Stimmen
Es wäre schön, wenn es Python 3-Versionen der Funktionen in den Antworten geben könnte.
0 Stimmen
Sicher gibt es eine Bibliothek, um dies zu tun, damit wir nicht selbst programmieren müssen. Xkcd versprach, dass Python so einfach ist wie
import antigravity
. Gibt es nicht so etwas wierequire 'prime'; Prime.take(10)
(Ruby)?0 Stimmen
Beachten Sie, dass Sie kein Set als Argument an
difference_update
übergeben müssen. Sie können einfachnumbers.difference_update(xrange(p*2, N+1, p))
tun. Das wird zumindest ein paar Millisekunden von Ihrer Zeit abziehen.2 Stimmen
Ich vermute, dass eine Python-Anbindung an die C++-Bibliothek primesieve um Größenordnungen schneller wäre als all diese.
4 Stimmen
@ColonelPanic Wie es sich herausstellt, habe ich github.com/jaredks/pyprimesieve für Py3 aktualisiert und zu PyPi hinzugefügt. Es ist sicherlich schneller als diese, aber nicht um Größenordnungen - eher etwa ~5x schneller als die besten numpy-Versionen.
0 Stimmen
Ich kenne den Geschwindigkeitsvergleich zu den bereits hier aufgelisteten Antworten nicht, ich würde jedoch empfehlen, sich sagemath.org anzusehen. Es handelt sich um ein Python-Krypto-Framework, das viele integrierte Funktionen hat, um die Dinge zu tun, nach denen Sie suchen.
4 Stimmen
@ColonelPanic: Ich denke, es ist angemessen, alte Antworten zu bearbeiten, um anzugeben, dass sie gealtert sind, da dies sie zu einer nützlicheren Ressource macht. Wenn die "akzeptierte" Antwort nicht mehr die beste ist, könnte man vielleicht eine Notiz in die Frage einfügen mit einem Update von 2015, um die Leute auf die aktuell beste Methode hinzuweisen.
0 Stimmen
Ich kann nicht glauben, dass kein Moderator diese Frage gelöscht hat. Sie bittet um Verbesserung in der Geschwindigkeit eines Algorithmus, der zugegebenermaßen nicht korrekt ist. Grüße, Albert
0 Stimmen
from sympy import sieve; sieve.extend(N);
0 Stimmen
Hey, das ist wirklich schneller Code. Du hast recht, der Code funktioniert für
n =10000
nicht, danumber.pop()
nicht das kleinste Element als ungeordnetes auslöst. Thread