Eine naive (und für große Zahlen ineffiziente) Methode ist
Code: Alles auswählen
def factorize(n): # wir überprüfen nicht, ob n ganzzahling und >0 ist, das müsste man aber eigentlich machen
if n == 1:
return [] #1 hat keine (prim)faktoren
if n % 2 == 0:
return [2] + factorize(n/2)
else:
for p in xrange(3, int(sqrt(n))+1, 2):
if n % p == 0:
return [p] + factorize(n/p)
# wenn wir bis hierhin kommen, ist n prim
return [n]
print factorize(99) # [3, 3, 11] 99 = 3 * 3 * 11
print factorize(7 * 11 * 13) # [7, 11, 13]
print factorize(1234567891) # [1234567891], ja das ist eine Primzahl
print factorize(31337) # [31337], und das auch, wie leet ;)
Zuerst werden die Sonderfälle 1 und eine gerade Zahl überprüft (eine gerade Zahl ist nicht unbedingt ein Sonderfall, aber so brauchen wir in der Hauptschleife nur ungerade Teilerkandidaten auszuprobieren).
Ansonsten wird einfach nacheinander versucht, durch eine ungerade Zahl zu teilen. Sobald ein Faktor (sagen wir einfach mal 7) gefunden wurde, wird er zusammen mit der Liste der Faktoren der Zahl n/7 zurückgegeben. Die Faktoren der Zahl n/7 werden ebenfalls durch die Funktion berechnet, es ist also eine rekursive Funktion.
Wenn bis sqrt(n) + 1 kein Faktor gefunden wurde, muss die aktuelle Zahl, die wir überprüfen, eine Primzahl sein. Warum?
Sagen wir mal, es gäbe eine Zahl N, die nur Faktoren hat, die größer als sqrt(N) sind.
Sei f nun ein beliebiger dieser Faktoren, dann gilt
N = f * rest, da f > sqrt(N) ist, gilt N > sqrt(N) * rest
---> N / sqrt(N) > rest
---> sqrt(N) > rest.
rest ist wegen N = f * rest aber auch ein Faktor von N aber kleiner als sqrt(N) -> Widerspruch.
Ich hoffe, du hast jetzt eine gute Vorlage, die zu selber weiterentwickeln kannst. Man kann diesen Algorithmus z. B. noch verbessern/beschleunigen, indem man nur durch Primzahlen zu teilen versucht.
PS: Die Zeile "if n % p == 0:" und die folgende könnte man auch so schreiben:
Code: Alles auswählen
x,rest = divmod(n,p)
if rest == 0:
return [p] + factorize(x)
so spart man sich eine extra Rechenoperation