En este post incluyo un script en python que implementa el Test de primalidad de Miller-Rabin, posiblemente el algoritmo probabilista más utilizado para conocer con un alto grado de certeza si un número es primo o compuesto.
La cuestión de conocer si un número dado es primo o compuesto se conoce como el problema de la primalidad.
Ya expliqué en este post la importancia que tiene esta cuestión en la criptografía moderna (por ejemplo, a la hora de generar el par de claves, pública y privada, para un usuario en el criptosistema RSA de cifrado asimétrico) y que no es un asunto trivial cuando se trata de números muy grandes, ya que no se pueden utilizar algoritmos deterministas para saber con seguridad matemática al 100% si un número dado es o no primo, por lo que se recurre a algoritmos probabilistas muy simples y eficiente (Test de primalidad) que nos pueden decir con un elevado nivel de confianza si un número es primo o compuesto, como es el caso del Test de primalidad de Miller-Rabin.
Además, en la citada entrada puse el pseudocódigo para implementarlo:
- Script python para implementar el test de primalidad de Miller-Rabin:
El script es el siguiente:
#!/usr/bin/env python # -*- coding: utf-8 -*- # TEST DE PRIMALIDAD DE MILLER-RABIN: # # Test para conocer si un determinado número es primo con un cierto nivel de confianza. # El valor de k (número de rondas a ejecutar) determina el nivel de confianza del test, # es decir, si tras el test el número en cuestión es declarado primo, la confianza en que # realmente lo sea es mayor cuanto mayor sea el valor de k con el que se ha ejecutado el # test. # # http://mikelgarcialarragan.blogspot.com/ from random import randint from time import time def test_miller_rabin(n,k): # n = número natural mayor que 1 e impar del que queremos conocer si es primo. # k = número de veces o rondas a ejecutar el test. # t = indicador de que n es primo con un cierto nivel de confianza (0: primo; 1: compuesto). # s = número de veces que 2 divide a n - 1. t = 0 s = 0 r = n - 1 while r%2 == 0: s+=1 r = r//2 i=0 while i in range(0, k) and t != 1: a = randint(2, n - 1) j = 0 y = pow(a, r, n) if y != 1 and y != n - 1: j = 1 while y != n - 1 and t != 1 and j <= s - 1: y = pow(y, 2, n) if y == 1: t = 1 else: j = j + 1 if y != n -1: t = 1 i = i + 1 if t == 0: return True else: return False def main(): # MENÚ: # Se presenta el menú para que se seleccione una opción. salir = False while not salir: print ("") print ("*** MENÚ *****************************************") print ("1. Test de primalidad de Miller-Rabin.") print ("2. Salir.") print ("") opcion = input("Por favor, seleccione una opción: ") if opcion == "1": print ("") print ("--- TEST DE PRIMALIDAD DE MILLER-RABIN:") # Se introducen el número natural mayor que 1 del que se desea conocer si es primo con un cierto # nivel de confianza y el número de rondas a ejecutar el test. n = k = "*" while not n.isnumeric() or int(n) <= 1: n = input('Introduzca el número natural mayor que 1 del que desea conocer si es primo: ') if n.isnumeric() and int(n) >= 2: if int(n) >= 2: if int(n) ==2: inicio_test = time() print("[+] 2 es el único número par primo.") print('[+] Tiempo de ejecucion del test en segundos:', time() - inicio_test) elif int(n) % 2 == 0: inicio_test = time() print("[+] El número", n, "no es primo. El único número par primo es el 2.") print('[+] Tiempo de ejecucion del test en segundos:', time() - inicio_test) else: while not k.isnumeric() or int(k) <= 0: k = input('Introduzca el número de rondas a ejecutar el test: ') if k.isnumeric() and int(k) >= 1: inicio_test = time() if test_miller_rabin(int(n),int(k)): print("[+] El número", n, "probablemente es primo.") else: print("[+] El número", n, "es compuesto.") print('[+] Tiempo de ejecucion del test en segundos:', time() - inicio_test) else: print ("*** ERROR: Número de rondas a ejecutar el test incorrecto.") else: print ("*** ERROR: El número del que desea conocer si es primo debe ser un número natural mayor que 1.") else: print ("*** ERROR: Número incorrecto. Por favor, introduzca el número natural mayor que 1 del que desea conocer si es primo.") elif opcion == "2": print ("*** FIN ******************************************") salir = True else: print ("*** ERROR: Opción no válida.") if __name__ == '__main__': main()
Lo ejecuto:
Comentarios
Publicar un comentario