R中的素数功能

use*_*367 11 primes r

我正在尝试创建一个函数来测试给定的整数是否为素数,我尝试使用以下代码:

tpn <- function(prime.num){

    if(prime.num==2){
        print("PRIME")
    } else {

    if(prime.num%%(2:(prime.num-1))!=0){
        print("PRIME")

    } else { 
        print("NOT PRIME")

}}}
Run Code Online (Sandbox Code Playgroud)

这不起作用,虽然我不明白为什么.我正在检查给定的数字是否可以被任何整数除以这个数字而没有余数.如果它不能,那么这个数字是素数.

我发现的另一个解决方案是

tpn <- function(pn){

    if(sum(pn/1:pn==pn%/%1:pn)==2)
            print("prime")

}
Run Code Online (Sandbox Code Playgroud)

这有效.虽然,我无法理解sum(pn/1:pn == pn%/%1:pn) == 2实际测试的内容.

flo*_*del 22

如果除法的结果等于整数除法的结果,则数字a可以被数字整除.任何整数都可以除以至少两个数字:和.素数是那些只能被这两者分开的数字.打破代码:ba / ba %/% bpn1pn

  1. pn / 1:pn是的划分结果通过1,2...,pn
  2. pn %/% 1:pn是整数除法的结果通过1,2...,pn
  3. sum(pn / 1:pn == pn %/% 1:pn)是多少这些是相等的,即整数除数的数量pn.如果这个数字是2,你有一个素数.

您的代码出了什么问题:if需要测试某些内容是否存在,TRUE或者FALSE您是否将整个向量传递给它.而且,你的逻辑错了.应该是:

is.prime <- function(num) {
   if (num == 2) {
      TRUE
   } else if (any(num %% 2:(num-1) == 0)) {
      FALSE
   } else { 
      TRUE
   }
}
Run Code Online (Sandbox Code Playgroud)

一旦你决定返回逻辑,你就可以缩短你的代码:

is.prime <- function(n) n == 2L || all(n %% 2L:max(2,floor(sqrt(n))) != 0)
Run Code Online (Sandbox Code Playgroud)

(其中包含@ Carl关于不检查所有数字的评论.)

  • 所以我知道这是迟到的,但是较短的版本说3不是素数,因为在这种情况下`floor(sqrt(n))`是1. (4认同)
  • 那么,把我的评论变成一个答案:-(.对不起,我会提到测试`2:prime.num-1`是非常浪费的,因为你可以大致停止在'sqrt(prime.num)'. (3认同)
  • @rawr IMO 1是素数。我不在乎Mathmos怎么说:) (2认同)
  • @geotheory我很欣赏你的勇气 (2认同)

Sei*_*ily 10

我刚刚尝试了is.prime代码示例.但是这个3不是素数; o)

改进版本使用天花板而不是地板操作.

is.prime <- function(n) n == 2L || all(n %% 2L:ceiling(sqrt(n)) != 0)
Run Code Online (Sandbox Code Playgroud)

最好!


use*_*503 6

您也可以使用matlab包中的isprime()函数。它也适用于向量参数:

library(matlab)

as.logical(isprime(7))
as.logical(isprime(42))

#> as.logical(isprime(7))
#[1] TRUE
#> as.logical(isprime(42))
#[1] FALSE
Run Code Online (Sandbox Code Playgroud)


raw*_*awr 5

查找素数的正则表达式

is.prime <- function(x) {
  x <- abs(as.integer(x))
  !grepl('^1?$|^(11+?)\\1+$', strrep('1', x))
}

(-100:100)[is.prime(-100:100)]
# [1]  -97 -89 -83 -79 -73 -71 -67 -61 -59 -53 -47 -43 -41 -37 -31 -29 -23 -19 -17 -13 -11  -7  -5  -3  -2
# [26]   2   3   5   7  11  13  17  19  23  29  31  37  41  43  47  53  59  61  67  71  73  79  83  89  97
Run Code Online (Sandbox Code Playgroud)

http://diswww.mit.edu/bloom-picayune.mit.edu/perl/10138


或者,如果你取从 1 到 的所有整数x,则除以没有余数的数应该是 2:1 和x

is.prime <- function(x)
  vapply(x, function(y) sum(y / 1:y == y %/% 1:y), integer(1L)) == 2L

(1:100)[is.prime(1:100)]
# [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Run Code Online (Sandbox Code Playgroud)

我知道正则表达式会最慢,但它仍然是我的最爱

is.prime <- function(x)
  vapply(x, function(y) sum(y / 1:y == y %/% 1:y), integer(1L)) == 2L

is.prime_regex <- function(x) {
  x <- abs(as.integer(x))
  !grepl('^1?$|^(11+?)\\1+$', strrep('1', x))
}

is.prime_Seily  <- function(n)
  vapply(n, function(y)
    y == 2L || all(y %% 2L:ceiling(sqrt(y)) != 0), logical(1L))

is.prime_flodel <- function(n)
  vapply(n, function(y)
    y == 2L || all(y %% 2L:max(2,floor(sqrt(y))) != 0), logical(1L))

x <- 1:1000

library('microbenchmark')
microbenchmark(
  is.prime(x),
  is.prime_regex(x),
  is.prime_Seily(x),
  is.prime_flodel(x),
  unit = 'relative'
)

# Unit: relative
#               expr       min        lq      mean    median        uq        max neval cld
#        is.prime(x)  8.593971  8.606353  8.805690  8.892905  9.724452 21.9886734   100  b 
#  is.prime_regex(x) 84.572928 86.200415 76.413036 86.895956 85.117796 25.7106323   100   c
#  is.prime_Seily(x)  1.000000  1.000000  1.000000  1.000000  1.000000  1.0000000   100 a  
# is.prime_flodel(x)  1.146212  1.147971  1.144839  1.146119  1.163302  0.9085948   100 a  
Run Code Online (Sandbox Code Playgroud)