有人可以用简单的术语解释这个Miller-Rabin Primality测试伪代码吗?

时间:2013-06-12 10:58:23

标签: 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 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

我从Miller-Rabin primality test上的维基百科文章中得到了这个。但是我无法理解它......我不是要理解它背后的数学,而只是在程序中实现它。在我看来,这个算法有点令人困惑。在vb.net中更好,更简单的伪代码或它的实现会很有帮助。

到目前为止编写的

EDIT 代码:

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

3 个答案:

答案 0 :(得分:3)

根据要求,这是简单的伪代码:

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 证人;通过设置 k 的值,您可以在4 ^ k 中确定错误的可能性为1次。大多数人在10到25之间的某个地方使用 k 的值。powerMod函数通过平方来执行取幂,并且提供的是你的语言没有为你提供的机会。< / p>

如果你想更多地了解这个测试背后的数学,我在我的博客上谦虚地推荐这个essay,其中还包括五种语言的实现,但它们都不是VBA。

编辑:虽然他没有这么说,但原始海报实际上想要做的是找到不到两百万的素数之和,从而解决项目欧拉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

这里使用的算法是两年前由希腊数学家发明的Eratosthenes的筛子。同样,解释和代码位于我博客的essay

答案 1 :(得分:2)

关键思想和概念(p代表素数)

  1. 费马的小定理。 (a ^(p-1)= 1(mod p))
  2. 如果p为素数且x ^ 2 = 1(mod p),则x = +1或-1(mod p)。
  3. 我们可以证明如下:

    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;对于某些r,或者^(s *(2 ^ r))= -1(mod p),使得0 <= r <1。 d,从它重复平方将始终产生1,最后a ^(p-1)= 1(mod p)。如果这些都不成立,则对于任何素数a,^(p-1)将不为1(否则将与事实#2相矛盾)。

    算法:

    1. 设p是我们必须测试素数的给定数字。
    2. 首先我们将p-1重写为(2 ^ d)* s。 (其中s为奇数且d> = 0)。
    3. 现在我们选择范围[1,n-1]中的一些,然后检查是否= 1(mod p)或^(s *(2 ^ r))= -1(mod p)。
    4. 如果两者都失败了,那么p肯定是复合的。否则p可能是素数。我们可以选择另一个并重复相同的测试。
    5. 我们可以在经过一定数量的迭代后停止并声称p是绝对复合的,或者它可能是素数。
    6. 小码: Miller-Rabin素性测试,迭代表示测试的准确性

      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;
      }
      

      关于性能的几点:

      可以证明,对于任何复合数p,当在上述测试中选择为“a”时,至少(3/4)小于p的数将证明p是复合的。这意味着如果我们进行1次迭代,则复合数作为素数返回的概率为(1/4)。对于k次迭代,测试失败的概率是(1/4)k或4(-k)。与Fermat的测试相比,此测试相对较慢,但对于任何特定的复合数字,它都没有分解,对于大多数应用来说,18-20次迭代是一个非常好的选择。

      PS:此函数计算(a * b)%c时考虑到a * b可能会溢出我已经在MILLER RABBIN TEST中使用过。

         long long mulmod(long long a,long long b,long long c)
         {
             long long x = 0,y=a%c;
             while(b > 0)
             {
                if(b%2 == 1)
                {
                    x = (x+y)%c;
                }
                y = (y*2)%c;
                b /= 2;
             }
             return x%c;
          }
      

答案 2 :(得分:2)

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!