Vb.net 有人能简单地解释一下这个Miller-Rabin素性测试伪代码吗?

Vb.net 有人能简单地解释一下这个Miller-Rabin素性测试伪代码吗?,vb.net,algorithm,primes,pseudocode,primality-test,Vb.net,Algorithm,Primes,Pseudocode,Primality Test,这是 Input: n > 3, an odd integer to be tested for primality; Input: k, a parameter that determines the accuracy of the test Output: composite if n is composite, otherwise probably prime Write n − 1 as (2^s)·d with d odd by factoring powers of 2 fro

这是

Input: n > 3, an odd integer to be tested for primality;
Input: k, a parameter that determines the accuracy of the test
Output: composite if n is composite, otherwise probably prime
Write n − 1 as (2^s)·d with d odd by factoring powers of 2 from n − 1
WitnessLoop: repeat k times:
   pick a random integer a in the range [2, n − 2]
   x ← a^d mod n
   if x = 1 or x = n − 1 then do next WitnessLoop
   repeat s − 1 times:
      x ← x^2 mod n
      if x = 1 then return composite
      if x = n − 1 then do next WitnessLoop
   return composite
return probably prime
这是我从维基百科网站上的文章中得到的。但我一直无法理解。。。。。。我不想理解它背后的数学原理,而只是想在程序中实现它。在我看来,这个算法有点混乱。一个更好、更简单的伪代码或它在vb.net中的实现会有所帮助

编辑到目前为止编写的代码:

Function Miller_Rabin(ByVal n As Integer) As Boolean
    If n <= 3 Then : Return True
    ElseIf n Mod 2 = 0 Then : Return False
    Else
        Dim k, s, a, d, x As Integer
        k = 3
        d = n - 1

        While d Mod 2 = 0
            d = d / 2
            s += 1
        End While

        For c = 1 To k
            a = Random(2, n - 1)
            x = a ^ d Mod n
            If x = 1 Or x = n - 1 Then GoTo skip
            For r = 1 To s - 1
                x = x ^ 2 Mod n
                If x = 1 Then
                    Return False
                    Exit Function
                Else
                    If x = n - 1 Then
                        GoTo skip
                    Else
                        Return False
                        Exit Function
                    End If
                End If
            Next
skip:   Next
        Return True
    End If
End Function

Function Random(ByVal x As Integer, ByVal n As Integer) As Integer
    Dim a As Integer = Now.Millisecond * Now.Second
skip:
    a = (a ^ 2 + 1) Mod (n + 1)
    If a < x Then
        GoTo skip
    Else
        Return a
    End If
End Function
函数Miller_Rabin(ByVal n作为整数)作为布尔值
如果n关键思想和概念(这里p代表质数):

  • 费马小定理。(a^(p-1)=1(mod p))
  • 如果p是素数且x^2=1(mod p),那么x=+1或-1(mod p)
  • 我们可以证明如下:

    x^2 = 1 ( mod p )
    x^2 - 1 = 0 ( mod p )
    (x-1)(x+1) = 0 ( mod p )
    
    现在,如果p不同时除以(x-1)和(x+1),并且它除以它们的乘积,那么它就不可能是素数,这是一个矛盾。因此,p要么除以(x-1),要么除以(x+1),因此x=+1或-1(mod p)

    假设p-1=2^d*s,其中s为奇数,d>=0。如果p是素数,那么as=1(mod p)在本例中,从as重复平方将始终产生1,因此(a^(p-1))%p将是1;或者a^(s*(2^r))=-1(mod p)表示一些r,使得0=0)
  • 现在我们在[1,n-1]范围内选取一些a,然后检查as=1(mod p)还是a^(s*(2^r))=-1(mod p)
  • 如果两者都失败了,那么p肯定是复合的。否则p可能是素数。我们可以选择另一个a并重复相同的测试
  • 我们可以在一些固定次数的迭代之后停止,并声称p肯定是复合的,或者它可能是素数
  • 小代码: 米勒-拉宾素性检验,迭代意味着检验的准确性

    bool Miller(long long p,int iteration)
    {
        if(p<2)
            return false;
    
        if(p!=2 && p%2==0){
                    return false;
    
            long long s=p-1;
            while(s%2==0)
            {
                    s/=2;
            }
            for(int i=0;i<iteration;i++)
            {
                    long long a=rand()%(p-1)+1;
                long long temp=s;
                    long long mod=modulo(a,temp,p);
                    while(temp!=p-1 && mod!=1 && mod!=p-1)
                {
                        mod=mulmod(mod,mod,p);
                        temp *= 2;
                    }
                    if(mod!=p-1 && temp%2==0)
                 {
                        return false;
                    }
             }
             return true;
    }
    

    VB实现使用十六进制转换函数来处理模幂运算之前的大量数字。评论中提供的示例:

    ' USAGE:
    ' Example: strResult = mpModExp("3c", "03", "face")
    ' computes (0x3c)^3 mod 0xface = 0x5b56
    ' or, in decimal, 60^3 mod 64206 = 23382
    ' Parameters may be hex strings of any length subject to limitations
    ' of VB and your computer. May take a long time!
    

    以下是简单的伪代码,如请求所示:

    function isStrongPseudoprime(n, a)
        d := n - 1; s := 0
        while d % 2 == 0
            d := d / 2
            s := s + 1
        t := powerMod(a, d, n)
        if t == 1 return ProbablyPrime
        while s > 0
            if t == n - 1
                return ProbablyPrime
            t := (t * t) % n
            s := s - 1
        return Composite
    
    function isPrime(n)
        for i from 1 to k
            a := randInt(2, n-1)
            if isStrongPseudoprime(n, a) == Composite
                return Composite
        return ProbablyPrime
    
    function powerMod(b, e, m)
        x := 1
        while e > 0
            if e % 2 == 1
                x := (b * x) % m
            b := (b * b) % m
            e := e // 2 # integer division
        return x
    
    isStrongPseudoprime
    函数测试a是否是n的合成的见证;请注意,如果
    isStrongPseudoprime
    返回
    Composite
    则该数字肯定是复合的,但与之相反的是
    ProbablyPrime
    ,因为该数字仍有可能是复合的。
    isPrime
    功能测试;通过设置k的值,可以确定错误的可能性为4^k中的1次机会。大多数人使用的k值介于10到25之间。
    powerMod
    函数通过平方运算执行幂运算,如果您的语言没有为您提供该函数,则会提供该函数

    如果你想知道更多关于这个测试背后的数学知识,我在我的博客上谦虚地推荐这个,其中也包括五种语言的实现,尽管它们都不是VBA

    编辑:虽然他没有这样说,但原始海报实际上想做的是找到少于200万的素数之和,从而解决Euler 10项目。循环从2到n的数字是求小于n的素数之和的一种非常低效的方法;相反,推荐的方法是使用筛子。再次输入伪代码:

    function sumPrimes(n)
        sum := 0
        sieve := makeArray(2..n, True)
        for p from 2 to n step 1
            if sieve[p]
                sum := sum + p
                for i from p * p to n step p
                    sieve[i] := False
        return sum
    

    这里使用的算法是埃拉托斯提尼筛,由一位希腊数学家在两千多年前发明。同样,在我的博客上有一个解释和代码。

    有一个问题,如果移植到VB.NET足够容易吗?这太复杂了。。。你能不能给我一个合适的伪代码?你在维基上发布的伪代码一点都不复杂,你有什么问题?如果您已经编写了一些代码,也许可以编辑您的问题,这样我们就可以看到您的困境。只有当它们涉及到非常大的数字时(大多数情况下),实现才是痛苦的。。。。给我几分钟…这是我写的代码。。。如果您有任何问题,请在评论中提出任何问题!我尝试在vb.net中实现您的代码。。。。。但它不起作用!这里是它的链接。。。我不知道vb.net。但是这肯定会在C++上运行。我在编程中使用过这个实现@威尔·内斯-谢谢你的编辑。。我在为代码的缩进而挣扎!不客气。:)要缩进/取消缩进,请选择一个段落,然后按Ctrl-K(或按编辑区域上方的“代码”按钮)。我已经实现了它,它可以工作。。。。除非我使用一个任意的精确整数,来找出大的数字是否是素数,否则它不起作用!像1298074214633706835075030044377087实际上是素数,但函数返回它作为复合!我可以确认你说的数字是素数。可能在某个中间值中存在溢出。程序中的所有变量都是大整数吗?我设法解决了这个问题。。。如果我让你为我测试你的实现会不会太麻烦?。。。。我想知道200万以下所有素数的总和,因为我的答案一直在变化。我展示的解决方案是伪代码,无法运行。我提到的这篇文章有五种语言的实现,都经过测试并且工作正常。如果希望素数之和小于n,则不必从2迭代到n并测试每个数的素数性,更好的算法是筛选。我将把它添加到上面给出的答案中,因为代码不能在注释中正确格式化。我知道它效率低下。。。。我只需要一个例子来测试我的实现。。。。顺便说一下,你的文章涵盖了基于数学的函数,而不是我所知道的语言,即C++和VB.NET。所以我得到了一些网站的帮助,并使它正常运行。无论如何,谢谢你的帮助D
    function sumPrimes(n)
        sum := 0
        sieve := makeArray(2..n, True)
        for p from 2 to n step 1
            if sieve[p]
                sum := sum + p
                for i from p * p to n step p
                    sieve[i] := False
        return sum