Miller-Rabin Primality Test经常为Prime数返回复合数

时间:2017-12-03 07:04:33

标签: java primes primality-test

我一直试图从头开始实现Miller-Rabin素性测试(只有原语和字符串),这些测试适用于64位整数(longs)。我已经尝试过来自Wikipedia的Java和伪代码,以及其他各种网站。到目前为止,只有非常小的数字才能正常工作。大多数数字都被错误地标记为复合数字,例如53或101.我已尝试跟踪代码的各个部分以查看问题所在。它似乎在最里面的循环中。我不知道具体问题是什么。任何帮助表示赞赏。谢谢!

这是我的代码:

public class PrimeTest
{
public static void main(String[] args)
{
    PrimeTest app = new PrimeTest();
}

private PrimeTest()
{
    long n = 53; // Change to any number. 53 is prime, but is reported as composite
    if (checkPrime(n, 10))
    {
        System.out.println(n + " is prime.");
    }
    else
    {
        System.out.println(n + " is not prime.");
    }
}

// Check if n is prime with 4^(-k) change of error
private boolean checkPrime(long n, int k)
{
    // Factor n-1 as d*2^s
    long d = n - 1;
    int s = 0;
    while (d % 2 == 0)
    {
        d /= 2;
        s++;
    }

    // Repeat k times for 4^-k accuracy
    for (int i = 0; i < k; i++)
    {
        long a = (long) ((Math.random() * (n - 3)) + 2);
        long x = modPow(a, d, n);
        if (x == 1 || x == (n - 1))
        {
            continue;
        }
        int r;
        for (r = 0; r < s; r++)
        {
            x = modPow(x, 2, n);
            if (x == 1)
            {
                return false;
            }
            if (x == (n - 1))
            {
                break;
            }
        }
        if (r == s)
        {
            return false;
        }
    }
    return true;
}

// Return (base^exp) % mod
private long modPow(long base, long exp, long mod)
{
    if (mod == 1)
    {
        return 0;
    }
    long result = 1;
    base = base % mod;
    while (exp > 0)
    {
        if ((exp & 1) == 0)
        {
            result = (result * base) % mod;
        }
        exp = exp >> 1;
        base = (base * base) % mod;
        if (base == 1)
        {
            break;
        }
    }
    return result;
}
}

1 个答案:

答案 0 :(得分:0)

modPow中的这一行:

if ((exp & 1) == 0)

错了,应该是

if ((exp & 1) == 1)