首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Miller-Rabin素性测试FIPS 186-3的实现

Miller-Rabin素性测试FIPS 186-3的实现
EN

Stack Overflow用户
提问于 2012-06-28 08:54:10
回答 2查看 1.4K关注 0票数 6

我正在尝试根据FIPS 186-3 C.3.1中的描述来实现米勒-拉宾素性检验。无论我做什么,我都不能让它工作。指令非常具体,我认为我没有遗漏任何东西,但我得到了非素数值的true

我做错什么了?

代码语言:javascript
复制
template <typename R, typename S, typename T>
T POW(R base, S exponent, const T mod){
    T result = 1;
    while (exponent){
        if (exponent & 1)
            result = (result * base) % mod;
        exponent >>= 1;
        base = (base * base) % mod;
    }
    return result;
}



// used uint64_t to prevent overflow, but only testing with small numbers for now
bool MillerRabin_FIPS186(uint64_t w, unsigned int iterations = 50){
    srand(time(0));
    unsigned int a = 0;
    uint64_t W = w - 1; // dont want to keep calculating w - 1
    uint64_t m = W;
    while (!(m & 1)){
        m >>= 1;
        a++;
    }

    // skipped getting wlen
    // when i had this function using my custom arbitrary precision integer class,
    // and could get len(w), getting it and using it in an actual RBG 
    // made no difference 

    for(unsigned int i = 0; i < iterations; i++){
        uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
        uint64_t z = POW(b, m, w);
        if ((z == 1) || (z == W))
            continue;
        else
            for(unsigned int j = 1; j < a; j++){
                z = POW(z, 2, w);
                if (z == W)
                    continue;
                if (z == 1)
                    return 0;// Composite
            }
    }
    return 1;// Probably Prime
}

这一点:

代码语言:javascript
复制
std::cout << MillerRabin_FIPS186(33) << std::endl;
std::cout << MillerRabin_FIPS186(35) << std::endl;
std::cout << MillerRabin_FIPS186(37) << std::endl;
std::cout << MillerRabin_FIPS186(39) << std::endl;
std::cout << MillerRabin_FIPS186(45) << std::endl;
std::cout << MillerRabin_FIPS186(49) << std::endl;

给我的是:

代码语言:javascript
复制
0
1
1
1
0
1
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-28 09:10:55

您的实现与Wikipedia的唯一不同之处在于您忘记了第二个返回复合语句。在循环的末尾应该有一个返回0。

编辑:正如Daniel指出的,还有第二个不同之处。continue是继续内部循环,而不是像它应该的那样继续外部循环。

代码语言:javascript
复制
for(unsigned int i = 0; i < iterations; i++){
    uint64_t b = (rand() % (W - 3)) + 2; // 2 <= b <= w - 2
    uint64_t z = POW(b, m, w);
    if ((z == 1) || (z == W))
        continue;
    else{
        int continueOuter = 0;
        for(unsigned int j = 1; j < a; j++){
            z = POW(z, 2, w);
            if (z == W)
                continueOuter = 1;
                break;
            if (z == 1)
                return 0;// Composite
        }
        if (continueOuter) {continue;}
    }
    return 0; //This is the line you're missing.
}
return 1;// Probably Prime

此外,如果输入是偶数,它将始终返回可能的素数,因为a为0。你应该在开始的时候加一个额外的检查。

票数 5
EN

Stack Overflow用户

发布于 2012-06-28 09:31:03

在内部循环中,

代码语言:javascript
复制
        for(unsigned int j = 1; j < a; j++){
            z = POW(z, 2, w);
            if (z == W)
                continue;
            if (z == 1)
                return 0;// Composite
        }

当使用z == W时,您应该使用break;而不是continue;。通过continueing,在该循环的下一次迭代中,如果有一个,z将变为1,并且候选可能被错误地声明为复合。这里,在小于100的素数中,17,41,73,89和97都会发生这种情况。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11236757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档