R-Lehmann素性检验中的模警告

R-Lehmann素性检验中的模警告,r,primes,R,Primes,我花了一点时间破解了lehmann素性测试的R实现。我借鉴的功能设计 这是我的密码: 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{

我花了一点时间破解了lehmann素性测试的R实现。我借鉴的功能设计

这是我的密码:

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))
}
经过一些调查,我相信这与浮点转换有关。非常大的数字被四舍五入,因此mod函数给出了错误的响应

现在是问题

  • 这是一个浮点问题吗?还是在我的实现中
  • 是有一个纯粹的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
    

    modexp如果您只使用base R,我会选择#2b。。。“R不擅长这个”。在R中,整数(您似乎没有使用)被限制为16位精度。超过该限制,您将得到舍入误差。您可能应该查看:package:gmp或package:Brobdingnag。包:gmp有大整数和大有理数类。

    当然,表示整数有问题。在R中,整数将正确表示为2^53-1,约为9e15。而术语
    y^((n-1)/2)
    即使对于小的数字也很容易超过这个值。您必须通过不断平方
    y
    并取模来计算
    (y^((n-1)/2))%%n
    。对应于
    (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)
    }
    

    primeTest感谢您的帮助。我不能说这对工作是至关重要的,但这一练习完全击败了我。但现在我知道了模幂运算,我可以快乐地死去。研究之后,我使用pow()函数在python中重写了该函数。我很高兴R中有一个实现。这个解决方案适用于一些数字。然而,当指数不是一个自然数时,modpower函数就会爆炸。这是包中的源代码。指数必须是一个自然数:地板(k)=天花板(k)。当n=4,(n-1)/2=1.5且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)
    }
    
    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