Skip to main content

Command Palette

Search for a command to run...

Miller-Rabin Primality Test

Updated
4 min read
💡
Thuật toán Miller-Rabin là một phương pháp kiểm tra tính nguyên tố nhanh, dựa trên lý thuyết số và được sử dụng để xác định liệu một số lớn có phải là số nguyên tố hay không. Đây là một thuật toán xác suất, có nghĩa là nó có thể cho kết quả sai (các số giả nguyên tố), nhưng xác suất sai số là rất nhỏ nếu số lần kiểm tra tăng lên. Thuật toán này đặc biệt hữu ích khi làm việc với các số rất lớn, thường được sử dụng trong mật mã học và các ứng dụng liên quan đến bảo mật.

Ý tưởng chủ đạo

Thuật toán Miller-Rabin dựa trên nguyên lý của định lý Fermat nhỏ:

Nếu $p$ là số nguyên tố, thì ta có \(a^p \equiv a (\bmod p)\).

💡
Chứng minh của định lý này, bạn có thể kiếm được từ rất nhiều nguồn trên mạng. Mình cũng đã nêu một chứng minh của định lý trong bài viết về thuật toán AKS, bạn có thể đọc lại nếu hứng thú.

Tuy nhiên, vấn đề là đối với một số nguyên $n$ bất kỳ thỏa mãn \(a^n \equiv a (\bmod n)\) với $a$ là số tự nhiên, thì chưa chắc $n$ đã là số nguyên tố. Nói cách khác, nếu $n$ vượt qua phép thử Fermat trên, vẫn tồn tại một khả năng nhỏ $n$ là hợp số. Thuật toán Miller-Rabin mở rộng phép thử Fermat từ nhận xét:

  • \(a^n \equiv a (\bmod n) \iff a^{n-1} \equiv 1 (\bmod n)\)

  • Với mọi $n$, luôn có thể phân tích \(n-1 = 2^s \times d\), với $d$ là số lẻ

  • Từ đó ta phân tích \(a^{n-1} \equiv 1 (\bmod n)\) thành: \(a^{n-1} - 1 = a^{2^s \times d} - 1 = (a^{2^{s-1} \times d} + 1)(a^{2^{s-2} \times d} + 1)\dots(a^d + 1)(a^d-1) \equiv 0 (\bmod n)\)Nếu $n$ là số nguyên tố thì phải tồn tại ít nhất một thừa số chia hết cho $n$.

Như vậy ta sẽ kiểm trả các điều kiện:

  • Hoặc \(n|(a^d-1) \implies a^d \equiv 1 (\bmod n)\)

  • Hoặc có ít nhất một thừa số \((a^{2^i\times d} + 1), 0\le i \le s-1\) chia hết cho $n$, hay \(a^{2^i\times d} \equiv -1 (\bmod n)\)

Nếu $n$ không thỏa cả 2 điều kiện trên thì $n$ chắc chắn là hợp số, ngược lại thì $n$ có khoảng 25% khả năng là một số nguyên tố. Như vậy, để chắc chắn hơn, ta có thể kiểm tra nhiều lần với nhiều giá trị $a$ khác nhau để tăng xác suất.

Thuật toán

Kiểm tra $n$ có phải số nguyên tố hay không, lưu ý rằng thuật toán dưới đây nếu trả về TRUE thì $n $ có thể là số nguyên tố, ngược lại nếu FALSE thì $n$ chắc chắc là hợp số.

  • Phân tích \(n = 2^s\times d +1\)

  • Chọn số ngẫu nhiên \(a \in [2, n-1]\):

    • Nếu \(a^d \bmod n = 1\): return TRUE
  • Cho \(i: 1 \to k-1:\)

    • Nếu \(a^{2^i\times d} \bmod n = 1\): return TRUE
  • Return FALSE

Cài đặt và Demo

Phân tích một số thành dạng \(2^s \times d\)

// factorize n to the format of 2^s * d
    function factorize(n) {
        let s = 0;
        let d = n;
        while (d % 2 == 0) {
            s++;
            d = d >> 1;
        }
        return [s, d];
    }

Thuật toán

function rabinMiller(n, s, d, a) {
            // first condition check a^d mod n = 1
            if (modPow(a, d, n) == 1) return true;

            // second condition check a^(2^i * d) mod n = n - 1
            for (let i = 0; i < s; i++) {
                if (modPow(a, (2**i) * d, n) == n - 1) return true;                
            }           

            // if both conditions fail, n is composite
            return false;
        }

Mình đã thử chạy thử thuật toán với 10 lần thử (10 lần chọn $a$ ngẫu nhiên) này để đếm xem có bao nhiêu số nguyên tố trong khoảng từ 1-10,000,000 và kết quả là có 664,579 số nguyên tố.

let total = 0;
let trials = 10;
for (let i = 0; i < 10000000; i++) {
    if (isPrime(i, trials)) {
        console.log(i);
        total++;
    }
}
console.log(`Total prime numbers: ${total}`);

Demo

More from this blog

L

Legos' writes and shares

49 posts

...interesting things by short notes and demos. Most of notes are in Vietnamese since too few of resources of the language and machine translation EN-VN are not good enough :)