R-Lehmann原始性测试中的模数警告

jde*_*son 3 primes r

我花了一点时间来攻击lehmann素性测试的R实现.我从http://davidkendal.net/articles/2011/12/lehmann-primality-test借来的功能设计

这是我的代码:

primeTest <- function(n, iter){
  a <- sample(1:(n-1), 1)
    lehmannTest <- function(y, tries){
    x <- ((y^((n-1)/2)) %% n)
    if (tries == 0) {
      return(TRUE)
            }else{          
      if ((x == 1) | (x == (-1 %% n))){
        lehmannTest(sample(1:(n-1), 1), (tries-1))
      }else{
    return(FALSE)
      }
    }
  }
  lehmannTest(a, iter)
}

primeTest(4, 50) # false
primeTest(3, 50) # true
primeTest(10, 50)# false
primeTest(97, 50) # gives false # SHOULD BE TRUE !!!! WTF

prime_test<-c(2,3,5,7,11,13,17 ,19,23,29,31,37)

for (i in 1:length(prime_test)) {
  print(primeTest(prime_test[i], 50))
}
Run Code Online (Sandbox Code Playgroud)

对于小素数它可以工作,但是当我到达~30时,我得到一个看起来很糟糕的消息,并且该功能停止正常工作:

2: In lehmannTest(a, iter) : probable complete loss of accuracy in modulus
Run Code Online (Sandbox Code Playgroud)

经过一番调查后,我认为它与浮点转换有关.非常大的数字是四舍五入的,因此mod函数给出了错误的响应.

现在的问题.

  1. 这是浮点问题吗?还是在我的实施中?
  2. 有没有一个纯粹的R解决方案或R只是坏在这?

谢谢

解:

在有关模幂运算算法的大反馈和一小时阅读后,我有一个解决方案.首先是制作我自己的模幂运算函数.基本思想是模块化乘法允许您计算中间结果.你可以在每次迭代后计算mod,因此永远不会得到一个巨大的令人讨厌的数字,它会淹没16位的R int.

modexp<-function(a, b, n){
    r = 1
    for (i in 1:b){
        r = (r*a) %% n
    }
    return(r)
}


primeTest <- function(n, iter){
   a <- sample(1:(n-1), 1)
    lehmannTest <- function(y, tries){
      x <- modexp(y, (n-1)/2, n)   
    if (tries == 0) {
      return(TRUE)
            }else{          
      if ((x == 1) | (x == (-1 %% n))){
        lehmannTest(sample(1:(n-1), 1), (tries-1))
        }else{
        return(FALSE)
         }
    }
  }
   if( n < 2 ){
     return(FALSE)
     }else if (n ==2) {
       return(TRUE)
       } else{
         lehmannTest(a, iter)
         }
}

primeTest(4, 50) # false
primeTest(3, 50) # true
primeTest(10, 50)# false
primeTest(97, 50) # NOW IS TRUE !!!!


prime_test<-c(5,7,11,13,17 ,19,23,29,31,37,1009)

for (i in 1:length(prime_test)) {
  print(primeTest(prime_test[i], 50))
}
#ALL TRUE
Run Code Online (Sandbox Code Playgroud)

Han*_* W. 5

当然,表示整数存在问题.在R中,整数将正确表示,最大为2 ^ 53 - 1,大约为9e15.y^((n-1)/2)即使对于少数人来说,这个词也会超过这个数字.您将不得不(y^((n-1)/2)) %% n通过连续平方y和取模数来计算.这对应于的二进制表示(n-1)/2.

即使是"真正的"数论理论程序就是这样 - 请参阅维基百科关于"模幂运算"的内容.也就是说应该提到像R(或Matlab和其他数值计算系统)这样的程序可能不是实现数论算法的适当环境,甚至可能不是小整数的播放领域.

编辑:原始包不正确您可以在包'pracma'中使用函数modpower(),如下所示:

primeTest <- function(n, iter){
  a <- sample(1:(n-1), 1)
    lehmannTest <- function(y, tries){
    x <- modpower(y, (n-1)/2, n)  # ((y^((n-1)/2)) %% n)
    if (tries == 0) {
      return(TRUE)
            }else{          
      if ((x == 1) | (x == (-1 %% n))){
        lehmannTest(sample(1:(n-1), 1), (tries-1))
      }else{
    return(FALSE)
      }
    }
  }
  lehmannTest(a, iter)
}
Run Code Online (Sandbox Code Playgroud)

以下测试成功,因为1009是此集合中唯一的素数:

prime_test <- seq(1001, 1011, by = 2)
for (i in 1:length(prime_test)) {
    print(primeTest(prime_test[i], 50))
}
# FALSE FALSE FALSE FALSE TRUE  FALSE
Run Code Online (Sandbox Code Playgroud)