C++ C+中的Miller-Rabin素性检验+;缺陷

C++ C+中的Miller-Rabin素性检验+;缺陷,c++,C++,我目前正在解决欧拉计划的问题216。 首先,我用Python实现了Miller-Rabin素性测试: alist=[2,3,5,7,11,13,17,19,23] def isPrime(n): s=0 d=n-1 while not d&1: s+=1 d/=2 for a in alist: if a>=n:continue compo=True val=pow(a,

我目前正在解决欧拉计划的问题216。 首先,我用Python实现了Miller-Rabin素性测试:

alist=[2,3,5,7,11,13,17,19,23]
def isPrime(n):
    s=0
    d=n-1
    while not d&1:
        s+=1
        d/=2
    for a in alist:
        if a>=n:continue
        compo=True
        val=pow(a,d,n)
        if val==1 or val==n-1:continue
        for r in range(s-1):
            val=val*val%n
            if val==n-1:
                compo=False
                break
        if(compo):return False
    return True

N=10000
cnt=0
for i in range(2,N+1):
    if isPrime(2*i*i-1):cnt+=1
print cnt
它看起来不错,因为PE中的示例表示N=10000个匹配项。但是Python比C++慢,所以我把这个代码翻译成C++。在这个问题中,N=5e7,所以我们应该使用
long
64位int,对于指数,我们应该使用128位int

#include <cstdio>
long long list[9]={2,3,5,7,11,13,17,19,23};
long long exp(int a,long long d,long long n){
    if (d==0)return 1LL;
    if (d&1){
        __int128_t tmp=exp(a,d-1,n);
        return tmp*a%n;
        //return exp(a,d-1,n)*a%n
    }
    __int128_t tmp=exp(a,d/2,n);
    tmp=tmp*tmp%n;
    return tmp;
}
bool isPrime(long long n){
    int s=0;
    long long d=n-1;
    while(!d&1){
        s++;
        d/=2;
    }
    for(int i=0;i<9;i++){
        int a=list[i];
        if(a>=n)continue;
        bool com=true;
        long long val=exp(a,d,n);
        if (val==1||val==n-1)continue;
        for (int r=0;r<s-1;r++){
            __int128_t tmp=val;
            tmp=tmp*tmp%n;
            val=tmp;
            if (val==n-1){
                com=false;
                break;
            }
        }
        if(com)return false;
    }
    return true;
}
int main(){
    long long N=10000;
    int cnt=0;
    for(long long i=2;i<=N;i++){
        if (isPrime(2LL*i*i-1))cnt++;
    }
    printf("%d \n",cnt);
    return 0;
}
#包括
长长列表[9]={2,3,5,7,11,13,17,19,23};
长-长exp(整数a、长-长d、长-长n){
如果(d==0)返回1LL;
如果(d&1){
__int128_t tmp=exp(a,d-1,n);
返回tmp*a%n;
//返回经验(a,d-1,n)*a%n
}
__int128_t tmp=exp(a,d/2,n);
tmp=tmp*tmp%n;
返回tmp;
}
bool isPrime(长n){
int s=0;
长d=n-1;
而(!d&1){
s++;
d/=2;
}
对于(int i=0;i=n)继续;
boolcom=true;
long val=exp(a,d,n);
如果(val==1 | | val==n-1)继续;

对于(int r=0;r而言,误差如下:

while(!d&1)
如果你看一下,你会发现
有优先级
3
&
只有优先级
10
。这意味着条件
!d&1
被解析为
(!d)&1
。但是你实际上想要
!(d&1)


对于未来,您如何找到这样的错误?Simple并行运行两个代码并比较一些值。因为您编写的
i=1939
是坏情况。我简单地在while循环后做了一个断点,比较了
s
d
的值,并注意到它们在Python版本中是不同的C++ C++版本。如果不想使用调试器,可以简单地在两个代码中插入一行,打印<代码> s < />代码>代码> d>代码> .< /p>尝试确定C++中的素数,而不是Python中的Prime。然后询问WalfRAMAlPHa,如果它是真的或不。也许这会给你一个线索。@2*1939*1939-1是一个素数,但实际上不是。乍一看,
(!d&1)
似乎很奇怪,你的意思是
(!(d&1))
?@M.M我想你是对的。现在它工作了!顺便说一句
d%2==0
(!d)&1
更容易阅读,而且没有优先级问题。