J'essaie d'implémenter une fonction primeFac()
qui prend en entrée un entier positif n
et renvoie une liste contenant tous les nombres de la factorisation de n
.
J'ai atteint ce stade, mais je pense qu'il serait préférable d'utiliser la récursion ici, sans savoir comment créer un code récursif ici, quel serait le scénario de base? commencer avec.
Mon code:
def primes(n):
primfac = []
d = 2
while (n > 1):
if n%d==0:
primfac.append(d)
# how do I continue from here... ?
Une division d'essai simple:
def primes(n):
primfac = []
d = 2
while d*d <= n:
while (n % d) == 0:
primfac.append(d) # supposing you want multiple factors repeated
n //= d
d += 1
if n > 1:
primfac.append(n)
return primfac
avec O(sqrt(n))
complexité (pire des cas). Vous pouvez facilement l’améliorer en utilisant le boîtier spécial 2 et en bouclant uniquement sur d
impair (ou en utilisant plus de diviseurs spéciaux plus petits et bouclant sur moins de diviseurs possibles).
Il s’agit d’une solution basée sur la compréhension, c’est peut-être ce qui se rapproche le plus d’une solution récursive en Python tout en pouvant être utilisée pour les grands nombres.
Vous pouvez obtenir les diviseurs appropriés avec une seule ligne:
divisors = [ d for d in xrange(2,int(math.sqrt(n))) if n % d == 0 ]
alors nous pouvons tester un nombre dans les diviseurs comme premier:
def isprime(d): return all( d % od != 0 for od in divisors if od != d )
qui teste qu'aucun autre diviseur divise d.
Ensuite, nous pouvons filtrer les diviseurs principaux:
prime_divisors = [ d for d in divisors if isprime(d) ]
Bien entendu, il peut être combiné dans une seule fonction:
def primes(n):
divisors = [ d for d in range(2,n//2+1) if n % d == 0 ]
return [ d for d in divisors if \
all( d % od != 0 for od in divisors if od != d ) ]
Ici, le\est là pour rompre la ligne sans jouer avec l'indentation Python.
Le module primefac fait des factorisations avec toutes les techniques sophistiquées que les mathématiciens ont développées au cours des siècles:
#!python
import primefac
import sys
n = int( sys.argv[1] )
factors = list( primefac.primefac(n) )
print '\n'.join(map(str, factors))
Voici ma version de la factorisation par division d'essai, qui intègre l'optimisation de la division par deux et les nombres entiers impairs proposés par Daniel Fischer:
def factors(n):
f, fs = 3, []
while n % 2 == 0:
fs.append(2)
n /= 2
while f * f <= n:
while n % f == 0:
fs.append(f)
n /= f
f += 2
if n > 1: fs.append(n)
return fs
Une amélioration de la division d’essai par deux et des nombres impairs est la factorisation roue, qui utilise un ensemble cyclique d’écarts entre les nombres premiers potentiels pour réduire considérablement le nombre de divisions d’essai. Ici nous utilisons une roue 2,3,5:
def factors(n):
gaps = [1,2,2,4,2,4,2,4,6,2,6]
length, cycle = 11, 3
f, fs, nxt = 2, [], 0
while f * f <= n:
while n % f == 0:
fs.append(f)
n /= f
f += gaps[nxt]
nxt += 1
if nxt == length:
nxt = cycle
if n > 1: fs.append(n)
return fs
Ainsi, print factors(13290059)
générera [3119, 4261]
. Les roues de factorisation ont la même complexité temporelle O(sqrt(n)) que la division d’essai normale, mais seront deux ou trois fois plus rapides dans la pratique.
J'ai beaucoup travaillé avec les nombres premiers sur mon blog . S'il vous plaît, n'hésitez pas à visiter et à étudier.
La plupart des solutions ci-dessus semblent quelque peu incomplètes. Une factorisation en nombre premier répète chaque facteur premier du nombre (e.g. 9 = [3 3])
.
De plus, les solutions ci-dessus pourraient être écrites comme des fonctions paresseuses pour faciliter la mise en œuvre.
L'utilisation desieve Of Eratosthenes
pour rechercher les nombres premiers à tester est optimale, mais; l'implémentation ci-dessus a utilisé plus de mémoire que nécessaire.
Je ne sais pas si/comment"wheel factorization"
serait supérieur à l'application de facteurs premiers uniquement, pour les tests de division de n.
Bien que ces solutions soient effectivement utiles, je suggérerais les fonctions suivantes: deux fonctions -
Fonction-1:
def primes(n):
if n < 2: return
yield 2
plist = [2]
for i in range(3,n):
test = True
for j in plist:
if j>n**0.5:
break
if i%j==0:
test = False
break
if test:
plist.append(i)
yield i
Fonction 2:
def pfactors(n):
for p in primes(n):
while n%p==0:
yield p
n=n//p
if n==1: return
list(pfactors(99999))
[3, 3, 41, 271]
3*3*41*271
99999
list(pfactors(13290059))
[3119, 4261]
3119*4261
13290059
J'ai modifié la réponse de @ user448810 pour qu'elle utilise des itérateurs d'itertools (et de python3.4, mais cela devrait être back-portable). La solution est environ 15% plus rapide.
import itertools
def factors(n):
f = 2
increments = itertools.chain([1,2,2], itertools.cycle([4,2,4,2,4,6,2,6]))
for incr in increments:
if f*f > n:
break
while n % f == 0:
yield f
n //= f
f += incr
if n > 1:
yield n
Notez que cela retourne un itérable, pas une liste. Enveloppez-le dans la liste () si c'est ce que vous voulez.
def get_prime_factors(number):
"""
Return prime factor list for a given number
number - an integer number
Example: get_prime_factors(8) --> [2, 2, 2].
"""
if number == 1:
return []
# We have to begin with 2 instead of 1 or 0
# to avoid the calls infinite or the division by 0
for i in xrange(2, number):
# Get remainder and quotient
rd, qt = divmod(number, i)
if not qt: # if equal to zero
return [i] + get_prime_factors(rd)
return [number]
facteurs premiers d'un nombre:
def primefactors(x):
factorlist=[]
loop=2
while loop<=x:
if x%loop==0:
x//=loop
factorlist.append(loop)
else:
loop+=1
return factorlist
x = int(input())
alist=primefactors(x)
print(alist)
Vous obtiendrez la liste . Si vous voulez obtenir les paires de facteurs premiers d’un nombre, essayez ceci: http://pythonplanet.blogspot.in/2015/09/list-of-all -unique-paires-of-prime.html
def prime_factors(num, dd=2):
while dd <= num and num>1:
if num % dd == 0:
num //= dd
yield dd
dd +=1
Beaucoup de réponses ci-dessus échouent sur les petits nombres premiers, par exemple. 3, 5 et 7. Ce qui précède est succinct et suffisamment rapide pour un usage ordinaire.
imprimer la liste (prime_factors (3))
[3]
Je voudrais partager mon code pour trouver les facteurs premiers du nombre donné par l'utilisateur:
a = int(input("Enter a number: "))
def prime(a):
b = list()
i = 1
while i<=a:
if a%i ==0 and i!=1 and i!=a:
b.append(i)
i+=1
return b
c = list()
for x in prime(a):
if len(prime(x)) == 0:
c.append(x)
print(c)
La plupart des réponses rendent les choses trop complexes. Nous pouvons le faire
def prime_factors(n):
num = []
#add 2 to list or prime factors and remove all even numbers(like sieve of ertosthenes)
while(n%2 == 0):
num.append(2)
n /= 2
#divide by odd numbers and remove all of their multiples increment by 2 if no perfectlly devides add it
for i in xrange(3, int(sqrt(n))+1, 2):
while (n%i == 0):
num.append(i)
n /= i
#if no is > 2 i.e no is a prime number that is only divisible by itself add it
if n>2:
num.append(n)
print (num)
Algorithme de GeeksforGeeks