确定性的米勒 - 拉宾实施

时间:2018-01-13 17:32:54

标签: c++ algorithm primes

我正在尝试使用确定性的Miller-Rabin算法实现素性检查函数,但结果并不总是正确的:当检查前1,000,000个数字时,它只找到78,495而不是78,498。

这是使用[2,7,61]作为基础获得的,根据维基百科,对于最大值为4,759,123,141的值应始终是正确的。
有趣的是,3个缺失的素数恰好是编写基数的原因(2,7和61)。

为什么会这样?我正在使用的代码如下:

T modular_power(T base, T exponent, T modulo) {
    base %= modulo;
    T result = 1;

    while (exponent > 0) {
        if (exponent % 2 == 1)
            result = (result * base) % modulo;
        base = (base * base) % modulo;
        exponent /= 2;
    }

    return result;
}

bool miller_rabin(const T& n, const vector<T>& witnesses) {
    unsigned int s = 0;
    T d = n - 1;
    while (d % 2 == 0) {
        s++;
        d /= 2;
    }

    for (const auto& a : witnesses) {
        if (modular_power<T>(a, d, n) == 1)
            continue;

        bool composite = true;
        for (unsigned int r = 0; r < s; r++) {
            if (modular_power<T>(a, (T) pow(2, r) * d, n) == n - 1) {
                composite = false;
                break;
            }
        }

        if (composite)
            return false;
    }

    return true;
}

bool is_prime(const T& n) {
    if (n < 4759123141)
        return miller_rabin(n, {2, 7, 61});
    return false; // will use different base
}

1 个答案:

答案 0 :(得分:3)

当基数和输入相同时,米勒 - 拉宾确实不起作用。在这种情况下会发生的是 d mod n为零(因为mod n为零,所以这实际上是将零增加到一些无关的功率),并且算法的其余部分无法& #34;逃逸&#34;从零开始,并得出结论,你正在处理复合材料。

作为一个特例,Miller-Rabin从不使用2的输入,因为没有可以选择的基础。 2本身是无用的,所以是1,没有任何东西。