La solution présentée par @agf est grande, mais on peut parvenir à ~50% plus rapide temps d'exécution pour un arbitraire impair nombre par la vérification de la parité. Comme les facteurs d'un nombre impair est toujours impair eux-mêmes, il n'est pas nécessaire de vérifier ces lorsque vous traitez avec des nombres impairs.
Je viens de commencer la résolution d'Euler puzzles de moi-même. Dans certains problèmes, un diviseur de contrôle est appelée à l'intérieur de deux boucles for imbriquées, et la performance de cette fonction est donc essentiel.
La combinaison de cet effet avec agf est une excellente solution, j'ai fini avec cette fonction.
from math import sqrt
def factors(n):
step = 2 if n%2 else 1
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))
Cependant, sur de petits nombres (~ < 100), les frais généraux supplémentaires à partir de cette altération peut provoquer la fonction de prendre plus de temps.
J'ai couru quelques tests afin de vérifier la vitesse. Ci-dessous est le code utilisé. Pour produire les différentes parcelles, j'ai changé l' X = range(1,100,1)
en conséquence.
import timeit
from math import sqrt
from matplotlib.pyplot import plot, legend, show
def factors_1(n):
step = 2 if n%2 else 1
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n))+1, step) if n % i == 0)))
def factors_2(n):
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(sqrt(n)) + 1) if n % i == 0)))
X = range(1,100000,1000)
Y = []
for i in X:
f_1 = timeit.timeit('factors_1({})'.format(i), setup='from __main__ import factors_1', number=10000)
f_2 = timeit.timeit('factors_2({})'.format(i), setup='from __main__ import factors_2', number=10000)
Y.append(f_1/f_2)
plot(X,Y, label='Running time with/without parity check')
legend()
show()
X = range(1,100,1)
Aucune différence significative ici, mais avec de plus grands nombres, l'avantage est évident:
X = range(1,100000,1000) (seuls les numéros impairs)
X = range(2,100000,100) (uniquement des chiffres)
X = range(1,100000,1001) (en alternance de la parité)