Теория чисел, кейс: как выбрать лучший алгоритм проверки простоты для числа порядка 10^12: пробное деление, решето, тест Миллера-Рабина — обсудите точность, сложность и практические ограничения
Кратко и по делу — три варианта для числа порядка 1012\,10^{12}1012: 1) Пробное деление (с простыми делителями) - Точность: детерминировано — даст ответ и (при желании) факторизацию. - Сложность: нужно делить до n\sqrt{n}n. Для n≈1012n\approx 10^{12}n≈1012 имеем n=106\sqrt{n}=10^6n=106 и число простых до этой границы π(106)≈78 498\pi(10^6)\approx 78\,498π(106)≈78498. То есть ~7.8⋅1047.8\cdot 10^47.8⋅104 делений по простым — очень дешёво на современных CPU. - Практические ограничения: нужно сгенерировать простые до n\sqrt{n}n (решето) или держать список; память и время для этого малы (решето до 10610^6106 — порядка мегабайтов и миллисекунд). Удобно, если нужен фактор числа. 2) Решето (Эратосфена / сегментированное) — применимо, если проверяются многие числа - Точность: детерминировано в смысле получения списка простых для пробного деления. - Сложность: создание решета до n\sqrt{n}n — около O(nloglogn)O(\sqrt{n}\log\log\sqrt{n})O(nloglogn); для n=106\sqrt{n}=10^6n=106 это тривиально. - Практические ограничения: выгодно при массовой проверке чисел (сегментированное решето по диапазонам). Для одного числа лишний шаг по сравнению с прямым MR, но даёт факторизацию. 3) Тест Миллера–Рабина (MR) - Точность: вероятностный, но для малых границ можно сделать детерминированным подбором баз. Для всех n<3 474 749 660 383n<3\,474\,749\,660\,383n<3474749660383 (≈3.47⋅10123.47\cdot10^{12}3.47⋅1012) достаточно тестировать базы 2,3,5,7,11,132,3,5,7,11,132,3,5,7,11,13 — тогда MR даёт точный результат для n≈1012n\approx10^{12}n≈1012. - Сложность: для каждого базового основания требуется несколько модульных возведений в степень; практическая стоимость для n∼1012n\sim10^{12}n∼1012 — доли миллисекунды. Ассимптотически: примерно O(k⋅log3n)O(k\cdot \log^3 n)O(k⋅log3n) битовых операций для kkk баз (на практике быстро). - Практические ограничения: нужно корректно реализовать безопасную модульную умножение (для 64-битных языков использовать 128-бит умножение или алгоритм умножения с редукцией). MR не даёт факторизацию, лишь прост/состав. Резюме/рекомендация - Для одиночного теста числа около 1012\,10^{12}1012: самый быстрый и гарантированный способ — детерминированный MR с базами {2,3,5,7,11,13}\{2,3,5,7,11,13\}{2,3,5,7,11,13}. - Если нужен фактор числа или вы проверяете много чисел: сгенерировать простые до n=106\sqrt{n}=10^6n=106 (решето) и делать пробное деление — также очень эффективно и детерминировано. - Важно: следите за корректной modular multiplication (использовать 128‑бит или безопасные алгоритмы), иначе возможны ошибки при больших промежуточных произведениях.
1) Пробное деление (с простыми делителями)
- Точность: детерминировано — даст ответ и (при желании) факторизацию.
- Сложность: нужно делить до n\sqrt{n}n . Для n≈1012n\approx 10^{12}n≈1012 имеем n=106\sqrt{n}=10^6n =106 и число простых до этой границы π(106)≈78 498\pi(10^6)\approx 78\,498π(106)≈78498. То есть ~7.8⋅1047.8\cdot 10^47.8⋅104 делений по простым — очень дешёво на современных CPU.
- Практические ограничения: нужно сгенерировать простые до n\sqrt{n}n (решето) или держать список; память и время для этого малы (решето до 10610^6106 — порядка мегабайтов и миллисекунд). Удобно, если нужен фактор числа.
2) Решето (Эратосфена / сегментированное) — применимо, если проверяются многие числа
- Точность: детерминировано в смысле получения списка простых для пробного деления.
- Сложность: создание решета до n\sqrt{n}n — около O(nloglogn)O(\sqrt{n}\log\log\sqrt{n})O(n loglogn ); для n=106\sqrt{n}=10^6n =106 это тривиально.
- Практические ограничения: выгодно при массовой проверке чисел (сегментированное решето по диапазонам). Для одного числа лишний шаг по сравнению с прямым MR, но даёт факторизацию.
3) Тест Миллера–Рабина (MR)
- Точность: вероятностный, но для малых границ можно сделать детерминированным подбором баз. Для всех n<3 474 749 660 383n<3\,474\,749\,660\,383n<3474749660383 (≈3.47⋅10123.47\cdot10^{12}3.47⋅1012) достаточно тестировать базы 2,3,5,7,11,132,3,5,7,11,132,3,5,7,11,13 — тогда MR даёт точный результат для n≈1012n\approx10^{12}n≈1012.
- Сложность: для каждого базового основания требуется несколько модульных возведений в степень; практическая стоимость для n∼1012n\sim10^{12}n∼1012 — доли миллисекунды. Ассимптотически: примерно O(k⋅log3n)O(k\cdot \log^3 n)O(k⋅log3n) битовых операций для kkk баз (на практике быстро).
- Практические ограничения: нужно корректно реализовать безопасную модульную умножение (для 64-битных языков использовать 128-бит умножение или алгоритм умножения с редукцией). MR не даёт факторизацию, лишь прост/состав.
Резюме/рекомендация
- Для одиночного теста числа около 1012\,10^{12}1012: самый быстрый и гарантированный способ — детерминированный MR с базами {2,3,5,7,11,13}\{2,3,5,7,11,13\}{2,3,5,7,11,13}.
- Если нужен фактор числа или вы проверяете много чисел: сгенерировать простые до n=106\sqrt{n}=10^6n =106 (решето) и делать пробное деление — также очень эффективно и детерминировано.
- Важно: следите за корректной modular multiplication (использовать 128‑бит или безопасные алгоритмы), иначе возможны ошибки при больших промежуточных произведениях.