Skip to Content

Tests de primalidad

Este artículo describe varios algoritmos para determinar si un número es primo o no.

División por tentativa

Por definición, un número primo no tiene ningún divisor distinto de 11 y de sí mismo. Un número compuesto tiene al menos un divisor adicional; llamémoslo dd. Naturalmente nd\frac{n}{d} también es un divisor de nn. Es fácil ver que o bien dnd \le \sqrt{n} o bien ndn\frac{n}{d} \le \sqrt{n}, por lo tanto uno de los divisores dd y nd\frac{n}{d} es n\le \sqrt{n}. Podemos usar esta información para comprobar la primalidad.

Intentamos hallar un divisor no trivial, comprobando si alguno de los números entre 22 y n\sqrt{n} es un divisor de nn. Si es un divisor, entonces nn definitivamente no es primo; en caso contrario, lo es.

bool isPrime(int x) { for (int d = 2; d * d <= x; d++) { if (x % d == 0) return false; } return x >= 2; }

Esta es la forma más simple de una comprobación de primalidad. Se puede optimizar esta función bastante, por ejemplo comprobando solo todos los números impares en el bucle, ya que el único primo par es 2. Varias de esas optimizaciones se describen en el artículo sobre factorización de enteros.

Test de primalidad de Fermat

Este es un test probabilístico.

El pequeño teorema de Fermat (véase también la función φ de Euler) afirma que, para un número primo pp y un entero aa coprimo, se cumple la siguiente ecuación:

ap11modpa^{p-1} \equiv 1 \bmod p

En general este teorema no se cumple para números compuestos.

Esto se puede usar para crear un test de primalidad. Elegimos un entero 2ap22 \le a \le p - 2 y comprobamos si la ecuación se cumple o no. Si no se cumple, p. ej. ap1≢1modpa^{p-1} \not\equiv 1 \bmod p, sabemos que pp no puede ser un número primo. En este caso llamamos a la base aa un testigo de Fermat (Fermat witness) de que pp es compuesto.

Sin embargo también es posible que la ecuación se cumpla para un número compuesto. Así que si la ecuación se cumple, no tenemos una demostración de primalidad. Solo podemos decir que pp es probablemente primo. Si resulta que el número es en realidad compuesto, llamamos a la base aa un mentiroso de Fermat (Fermat liar).

Ejecutando el test para todas las bases aa posibles, de hecho podemos demostrar que un número es primo. Sin embargo esto no se hace en la práctica, ya que es mucho más trabajo que simplemente hacer división por tentativa. En su lugar, el test se repetirá varias veces con elecciones aleatorias de aa. Si no encontramos ningún testigo de que el número es compuesto, es muy probable que de hecho sea primo.

bool probablyPrimeFermat(int n, int iter=5) { if (n < 4) return n == 2 || n == 3; for (int i = 0; i < iter; i++) { int a = 2 + rand() % (n - 3); if (binpower(a, n - 1, n) != 1) return false; } return true; }

Usamos exponenciación binaria para calcular de forma eficiente la potencia ap1a^{p-1}.

Hay una mala noticia, sin embargo: existen algunos números compuestos para los que an11modna^{n-1} \equiv 1 \bmod n se cumple para todo aa coprimo con nn, por ejemplo para el número 561=31117561 = 3 \cdot 11 \cdot 17. Tales números se llaman números de Carmichael. El test de primalidad de Fermat solo puede identificar estos números si tenemos una inmensa suerte y elegimos una base aa con gcd(a,n)1\gcd(a, n) \ne 1.

El test de Fermat se sigue usando en la práctica, ya que es muy rápido y los números de Carmichael son muy raros. P. ej. solo existen 646 de esos números por debajo de 10910^9.

Test de primalidad de Miller-Rabin

El test de Miller-Rabin extiende las ideas del test de Fermat.

Para un número impar nn, n1n-1 es par y podemos extraer todas las potencias de 2. Podemos escribir:

n1=2sd, with d odd.n - 1 = 2^s \cdot d,~\text{with}d\text{odd}.

Esto nos permite factorizar la ecuación del pequeño teorema de Fermat:

an11modna2sd10modn(a2s1d+1)(a2s1d1)0modn(a2s1d+1)(a2s2d+1)(a2s2d1)0modn(a2s1d+1)(a2s2d+1)(ad+1)(ad1)0modnan11modnamp;a2sd10modnamp;(a2s1d+1)(a2s1d1)0modnamp;(a2s1d+1)(a2s2d+1)(a2s2d1)0modnamp;amp;(a2s1d+1)(a2s2d+1)(ad+1)(ad1)0modn\begin{array}{rl} a^{n-1} \equiv 1 \bmod n &amp;\Longleftrightarrow a^{2^s d} - 1 \equiv 0 \bmod n \\ &amp;\Longleftrightarrow (a^{2^{s-1} d} + 1) (a^{2^{s-1} d} - 1) \equiv 0 \bmod n \\ &amp;\Longleftrightarrow (a^{2^{s-1} d} + 1) (a^{2^{s-2} d} + 1) (a^{2^{s-2} d} - 1) \equiv 0 \bmod n \\ &amp;\quad\vdots \\ &amp;\Longleftrightarrow (a^{2^{s-1} d} + 1) (a^{2^{s-2} d} + 1) \cdots (a^{d} + 1) (a^{d} - 1) \equiv 0 \bmod n \\ \end{array}

Si nn es primo, entonces nn tiene que dividir a uno de estos factores. Y en el test de primalidad de Miller-Rabin comprobamos exactamente esa afirmación, que es una versión más estricta de la afirmación del test de Fermat. Para una base 2an22 \le a \le n-2 comprobamos si o bien

ad1modna^d \equiv 1 \bmod n

se cumple, o bien

a2rd1modna^{2^r d} \equiv -1 \bmod n

se cumple para algún 0rs10 \le r \le s - 1.

Si encontramos una base aa que no satisface ninguna de las igualdades anteriores, entonces encontramos un testigo de que nn es compuesto. En este caso hemos demostrado que nn no es un número primo.

De forma similar al test de Fermat, también es posible que el conjunto de ecuaciones se cumpla para un número compuesto. En ese caso la base aa se llama un mentiroso fuerte (strong liar). Si una base aa satisface las ecuaciones (una de ellas), nn es solo primo probable fuerte (strong probable prime). Sin embargo, no hay números como los de Carmichael, en los que todas las bases no triviales mientan. De hecho es posible mostrar que a lo sumo 14\frac{1}{4} de las bases pueden ser mentirosos fuertes. Si nn es compuesto, tenemos una probabilidad de 75%\ge 75% de que una base aleatoria nos diga que es compuesto. Haciendo varias iteraciones, eligiendo distintas bases aleatorias, podemos decir con probabilidad muy alta si el número es verdaderamente primo o si es compuesto.

Aquí hay una implementación para enteros de 64 bits.

using u64 = uint64_t; using u128 = __uint128_t; u64 binpower(u64 base, u64 e, u64 mod) { u64 result = 1; base %= mod; while (e) { if (e & 1) result = (u128)result * base % mod; base = (u128)base * base % mod; e >>= 1; } return result; } bool check_composite(u64 n, u64 a, u64 d, int s) { u64 x = binpower(a, d, n); if (x == 1 || x == n - 1) return false; for (int r = 1; r < s; r++) { x = (u128)x * x % n; if (x == n - 1) return false; } return true; }; bool MillerRabin(u64 n, int iter=5) { // devuelve true si n es probablemente primo; si no, devuelve false. if (n < 4) return n == 2 || n == 3; int s = 0; u64 d = n - 1; while ((d & 1) == 0) { d >>= 1; s++; } for (int i = 0; i < iter; i++) { int a = 2 + rand() % (n - 3); if (check_composite(n, a, d, s)) return false; } return true; }

Antes del test de Miller-Rabin se puede comprobar adicionalmente si alguno de los primeros números primos es un divisor. Esto puede acelerar mucho el test, ya que la mayoría de los números compuestos tienen divisores primos muy pequeños. P. ej. el 88%88% de todos los números tiene un factor primo menor que 100100.

Versión determinista

Miller mostró que es posible hacer el algoritmo determinista comprobando solo todas las bases O((lnn)2)\le O((\ln n)^2). Bach dio después una cota concreta: solo es necesario probar todas las bases a2ln(n)2a \le 2 \ln(n)^2.

Esto sigue siendo una cantidad bastante grande de bases. Así que se ha invertido bastante poder de cómputo en hallar cotas más bajas. Resulta que, para probar un entero de 32 bits, solo es necesario comprobar las primeras 4 bases primas: 2, 3, 5 y 7. El menor número compuesto que falla este test es 3,215,031,751=151751283513,215,031,751 = 151 \cdot 751 \cdot 28351. Y para probar un entero de 64 bits basta con comprobar las primeras 12 bases primas: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 y 37.

Esto da lugar a la siguiente implementación determinista:

bool MillerRabin(u64 n) { // devuelve true si n es primo; si no, devuelve false. if (n < 2) return false; int r = 0; u64 d = n - 1; while ((d & 1) == 0) { d >>= 1; r++; } for (int a : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) { if (n == a) return true; if (check_composite(n, a, d, r)) return false; } return true; }

También es posible hacer la comprobación con solo 7 bases: 2, 325, 9375, 28178, 450775, 9780504 y 1795265022. Sin embargo, como estos números (excepto 2) no son primos, hay que comprobar adicionalmente si el número que se está comprobando es igual a algún divisor primo de esas bases: 2, 3, 5, 13, 19, 73, 193, 407521, 299210837.

Problemas de práctica