【发布时间】:2011-12-20 19:15:05
【问题描述】:
我花了一点时间破解了 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))
}
对于小的素数,它可以工作,但是当我大约 30 左右时,我会收到一条看起来很糟糕的消息,并且该功能停止正常工作:
2: In lehmannTest(a, iter) : probable complete loss of accuracy in modulus
经过一些调查,我认为这与浮点转换有关。非常大的数字会四舍五入,因此 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
【问题讨论】: