Hola, ¿cómo están?
El caso es que no puedo mejorar el tiempo que tarda el programa en mostrar los números
perfectos desde 1 a 100000, 6-28-496 y 8128 luego no finaliza nunca, si alguien me ayuda
a solucionar esto muy agradecido. -
Código:
def n_perfecto(n):
sumatorio = 0
for i in range(1, n):
if n % i == 0:
sumatorio += i
return sumatorio == n
n = 1
print('\n === Números perfectos ===\n')
while n < 100000:
if n_perfecto(n):
print(f'{str(n).rjust(10, " ")}')
n += 1
Saludos.
Hola Daniel, ¿cómo estás? Es interesante el programa (no conocía el concepto de número perfecto). Ahora, por lo que pude investigar, el siguiente número sería 33.550.336; es natural que el código se tome su tiempo. Hay dos cosas que puedes hacer en estos casos para que el script corra más rápido:
- Buscar un algoritmo más eficiente en lugar de ir número por número calculando la sumatoria de sus divisores. Por ejemplo, a simple vista, parece ser un patrón que un número perfecto es siempre mayor al doble de su inmediatamente anterior: 28 es mayor que el doble de 6, 496 es mayor que el doble de 28, etc. Sabiendo esto puedes hacer que tu código se ahorre el procesamiento de varios números y así optimizar el rendimiento en general (aunque insisto en que no puedo probar que sea realmente una propiedad de estos números).
- Compilar el código con Cython. Algo similar hice en este artículo: https://recursospython.com/guias-y-manuales/obtener-lista-numeros-primos/. Así tu algoritmo es ejecutado directamente por el procesador, sin el intérprete de Python de intermediario.
Saludos!
Buen día.
Francisco luego que me tranquilice un poco voy a analizar con detenimiento lo que propones, estoy muy alborotado con este tema, ahora te pido un pequeño esfuerzo y favor, encontré este algoritmo y me pareció interesante solo que no logro inplementarlo, no sé dónde poner el print para mostrar los números perfectos y si estoy llamando a la función correcta. -
Página
Código:
#!/usr/bin/env python
def getPerfect(n) :
return 2**(n - 1) * (2**n - 1)
def isPrimal(n) :
for i in range(2, n) :
if (n % i == 0) :
return False
return True
def getGreaterPerfectNumSmallerThan(num) :
for i in range(num) :
m = 2**i - 1
if (isPrimal(m)) :
if (getPerfect(i) > num) :
return perfect
perfect = getPerfect(i)
return perfect
n = 1
while n < 100000:
getGreaterPerfectNumSmallerThan(n)
n += 1
Saludos.
El código al parecer está pensado para retornar únicamente un número perfecto:
Código:
print(getGreaterPerfectNumSmallerThan(100000000)) # 33550336
Pero puede retocarse un poco para que retorne una lista:
Código:
def getGreaterPerfectNumSmallerThan(num):
for i in range(num) :
m = 2**i - 1
if (isPrimal(m)) :
perfect = getPerfect(i)
if perfect > num:
return
else:
if i > 1:
yield getPerfect(i)
# [6, 28, 496, 8128, 33550336]
print(list(getGreaterPerfectNumSmallerThan(100000000)))
Incluso esta otra función derivada que no tiene ningún límite:
Código:
def getPerfectNums():
i = 0
while True:
m = 2**i - 1
if (isPrimal(m)) :
perfect = getPerfect(i)
if i > 1:
print(getPerfect(i))
i += 1
getPerfectNums()
Saludos!
Hola, Francisco gracias por el código.
En realidad esperaba sacar más provecho, me había entusiasmado con descubrir el octavo número perfecto pero ahora me entero que hay como 20 y unos de los últimos tiene como 26000 dígitos. -
Cuando avance un poco más voy a compilar con Cython, a ver que pasa. -
Bueno es todo, gracias y un abrazo. -