Перейти до основного вмісту

Тести простоти

У цій статті описано кілька алгоритмів, що дозволяють визначити, чи є число простим.

Коли підходить цей алгоритм?
  • Чи потрібно перевірити простоту окремих великих чисел (до 1018\approx 10^{18}), а не всіх чисел до nn? (якщо треба список усіх простих до nnРешето Ератосфена)
  • Чи число занадто велике для пробних ділень за O(n)O(\sqrt{n}), тож потрібен імовірнісний/детермінований тест Міллера — Рабіна?
  • Чи достатньо відповіді «просте / складене» без самого розкладу на множники? (якщо потрібні множники → Факторизація)

Пробні ділення

За означенням просте число не має жодних дільників, окрім 11 і самого себе. Складене число має принаймні один додатковий дільник, назвемо його dd. Природно, що nd\frac{n}{d} також є дільником nn. Легко бачити, що або dnd \le \sqrt{n}, або ndn\frac{n}{d} \le \sqrt{n}, а отже один із дільників dd і nd\frac{n}{d} не перевищує n\sqrt{n}. Цю інформацію ми можемо використати для перевірки простоти.

Ми намагаємося знайти нетривіальний дільник, перевіряючи, чи є якесь із чисел від 22 до n\sqrt{n} дільником nn. Якщо це дільник, то nn точно не є простим, інакше є.

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

Це найпростіша форма перевірки на простоту. Цю функцію можна суттєво оптимізувати, наприклад перевіряючи в циклі лише непарні числа, оскільки єдине парне просте число — це 2. Кілька таких оптимізацій описано в статті про факторизацію цілих чисел.

Тест Ферма

Це ймовірнісний тест.

Мала теорема Ферма (див. також функцію Ейлера) стверджує, що для простого числа pp і взаємно простого з ним цілого aa виконується така рівність:

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

У загальному випадку для складених чисел ця теорема не виконується.

Це можна використати для побудови тесту простоти. Ми обираємо ціле 2ap22 \le a \le p - 2 і перевіряємо, чи виконується рівність. Якщо вона не виконується, тобто ap1≢1modpa^{p-1} \not\equiv 1 \bmod p, то ми знаємо, що pp не може бути простим числом. У цьому випадку ми називаємо основу aa свідком Ферма складеності pp.

Однак можливо й так, що рівність виконується для складеного числа. Тож якщо рівність виконується, ми не маємо доведення простоти. Ми можемо лише сказати, що pp ймовірно просте. Якщо виявиться, що число насправді складене, ми називаємо основу aa брехуном Ферма.

Виконавши тест для всіх можливих основ aa, ми справді можемо довести, що число просте. Однак на практиці так не роблять, оскільки це значно витратніше, ніж просто виконати пробні ділення. Натомість тест повторюють кілька разів з випадковим вибором aa. Якщо ми не знаходимо жодного свідка складеності, то дуже ймовірно, що число насправді просте.

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;
}

Для ефективного обчислення степеня ap1a^{p-1} ми використовуємо бінарне піднесення до степеня.

Однак є одна погана новина: існують складені числа, для яких an11modna^{n-1} \equiv 1 \bmod n виконується для всіх aa, взаємно простих з nn, наприклад для числа 561=31117561 = 3 \cdot 11 \cdot 17. Такі числа називають числами Кармайкла. Тест Ферма може виявити ці числа лише в тому випадку, якщо нам неймовірно пощастить і ми оберемо основу aa з gcd(a,n)1\gcd(a, n) \ne 1.

Тест Ферма все ще використовують на практиці, оскільки він дуже швидкий, а числа Кармайкла трапляються дуже рідко. Наприклад, нижче від 10910^9 існує лише 646 таких чисел.

Тест Міллера–Рабіна

Тест Міллера–Рабіна розвиває ідеї тесту Ферма.

Для непарного числа nn значення n1n-1 є парним, і ми можемо винести всі степені двійки. Можемо записати:

n1=2sd, де d непарне.n - 1 = 2^s \cdot d,~\text{де}~d~\text{непарне}.

Це дозволяє нам розкласти на множники рівність із малої теореми Ферма:

an11modna2sd10modn(a2s1d+1)(a2s1d1)0modn(a2s1d+1)(a2s2d+1)(a2s2d1)0modn(a2s1d+1)(a2s2d+1)(ad+1)(ad1)0modn\begin{array}{rl} a^{n-1} \equiv 1 \bmod n &\Longleftrightarrow a^{2^s d} - 1 \equiv 0 \bmod n \\\\ &\Longleftrightarrow (a^{2^{s-1} d} + 1) (a^{2^{s-1} d} - 1) \equiv 0 \bmod n \\\\ &\Longleftrightarrow (a^{2^{s-1} d} + 1) (a^{2^{s-2} d} + 1) (a^{2^{s-2} d} - 1) \equiv 0 \bmod n \\\\ &\quad\vdots \\\\ &\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}

Якщо nn просте, то nn має ділити один із цих множників. Саме це твердження ми й перевіряємо в тесті Міллера–Рабіна, і воно є суворішою версією твердження тесту Ферма. Для основи 2an22 \le a \le n-2 ми перевіряємо, чи виконується або

ad1modna^d \equiv 1 \bmod n

або

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

для деякого 0rs10 \le r \le s - 1.

Якщо ми знайшли основу aa, яка не задовольняє жодну з наведених рівностей, то ми знайшли свідка складеності nn. У цьому випадку ми довели, що nn не є простим числом.

Подібно до тесту Ферма, можливо й так, що набір рівнянь задовольняється для складеного числа. У цьому випадку основу aa називають сильним брехуном. Якщо основа aa задовольняє рівняння (одне з них), то nn лише сильно ймовірно просте. Однак немає чисел на кшталт чисел Кармайкла, для яких брешуть усі нетривіальні основи. Насправді можна показати, що сильними брехунами можуть бути щонайбільше 14\frac{1}{4} основ. Якщо nn складене, то з імовірністю 75%\ge 75\% випадкова основа повідомить нам, що воно складене. Виконавши кілька ітерацій з різними випадковими основами, ми можемо з дуже високою ймовірністю сказати, чи число справді просте, чи воно складене.

Ось реалізація для 64-бітних цілих чисел.

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) { // повертає true, якщо n ймовірно просте, інакше повертає 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;
}

Перед тестом Міллера–Рабіна можна додатково перевірити, чи не є якесь із перших кількох простих чисел дільником. Це може значно пришвидшити тест, оскільки більшість складених чисел мають дуже малі прості дільники. Наприклад, 88%88\% усіх чисел мають простий множник, менший за 100100.

Детермінований варіант

Міллер показав, що алгоритм можна зробити детермінованим, перевіряючи лише всі основи O((lnn)2)\le O((\ln n)^2). Пізніше Бах дав конкретну межу: достатньо перевірити всі основи a2ln(n)2a \le 2 \ln(n)^2.

Це все ще доволі велика кількість основ. Тому люди вклали чимало обчислювальної потужності в пошук нижчих меж. Виявляється, для перевірки 32-бітного цілого достатньо перевірити перші 4 прості основи: 2, 3, 5 і 7. Найменше складене число, що проходить цей тест помилково, — це 3,215,031,751=151751283513,215,031,751 = 151 \cdot 751 \cdot 28351. А для перевірки 64-бітного цілого достатньо перевірити перші 12 простих основ: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 і 37.

Це дає таку детерміновану реалізацію:

bool MillerRabin(u64 n) { // повертає true, якщо n просте, інакше повертає 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;
}

Перевірку також можна виконати лише з 7 основами: 2, 325, 9375, 28178, 450775, 9780504 і 1795265022. Однак, оскільки ці числа (окрім 2) не прості, потрібно додатково перевірити, чи не дорівнює число, яке ви перевіряєте, якомусь простому дільнику цих основ: 2, 3, 5, 13, 19, 73, 193, 407521, 299210837.

Задачі для практики

Відеоматеріали