如何在R中找到连续的复合数

时间:2015-09-04 11:38:11

标签: r algorithm algebra number-theory

我想要第一个'n'个连续的复合数

我搜索命令找到连续的复合数字,但我得到了结果证明了这个定理。我没有得到任何命令..请帮助我在R中解决这个问题。

3 个答案:

答案 0 :(得分:2)

这是另一种选择:

n_composite <- function(n) {

  s <- 4L
  i <- 1L
  vec <- numeric(n)
  while(i <= n) {

    if(any(s %% 2:(s-1) == 0L)) {
      vec[i] <- s
      i <- i + 1L

    }

    s <- s + 1L
  }

  vec
}

它使用基本控制流来循环通过正整数索引复合。

<强>基准

all.equal(find_N_composites(1e4), n_composite(1e4))
[1] TRUE

library(microbenchmark)
microbenchmark(

  Mak = find_N_composites(1e4),
  plafort = n_composite(1e4),
  times=5

  )

Unit: milliseconds
    expr       min        lq      mean    median        uq
     Mak 2304.8671 2347.9768 2397.0620 2376.4306 2475.2368
 plafort  508.8132  509.3055  522.1436  509.3608  530.4311
       max neval cld
 2480.7988     5   b
  552.8076     5  a 

答案 1 :(得分:1)

@Pierre Lafortune的代码很整洁而且不会太慢,但我想提出另一种方法,这种方法要快得多。

从另一个角度解决问题,在R中找到第一个n复合数字可以转换为“获取第一个n+k整数并删除素数”。这很快,因为生成序列1:(n+k)几乎没有时间,并且有非常复杂的算法可以找到可用的素数,一个实现是numbers::Primes()

序列需要以n+k结束,因为在第一个n整数内,会有一些(k1)素数需要被替换。请注意,范围(n+1):(n+k1)也可能包含k2素数,这些素数也需要替换。在on,on和on,......这将需要一个递归结构。

皮埃尔的答案基本上做了类似的事情:他迭代地检查整数是否是复合数(非素数)并继续直到找到足够的复合数。然而,这有一个缺点:找到(非)素数的算法相当幼稚(与其他算法相比,找到素数;没有预期的进攻)。另一方面,该解决方案不涉及上述任何整数范围内可能的素数的递归问题。

我想建议的递归解决方案如下:

library(numbers)

n_composite2 <- function(n, from = 2) {

  endRange <- from + n - 1
  numbers <- seq(from = from, to = endRange)
  primes <- Primes(n1 = from, n2 = endRange)
  composites <- numbers[!(numbers %in% primes)]
  nPrimes <- length(primes)
  if (nPrimes >= 1) return(c(composites, n_composite2(nPrimes, from = endRange + 1)))

  return(composites)
}

这将生成一系列整数(潜在复合),然后使用numbers::Primes()查找该范围内的素数并将其从序列中移除。如果某些数字已被删除,则该函数会再次调用自身,这次计算[number of primes in previous step]复合并启动上一步停止的序列。

如果怀疑这是否真的有效,这里检查皮埃尔的解决方案(n_composite()):

> all(n_composite(1e4) == n_composite2(1e4))
[1] TRUE

比较两个函数,n_composite2()大约快19倍:

library(microbenchmark)
microbenchmark(
  "n_composite2" = n_composite2(1e4),
  "n_composite" = n_composite(1e4),
  times=5
)

Unit: milliseconds
         expr       min        lq      mean    median        uq       max neval
 n_composite2  34.44039  34.51352  35.10659  34.71281  35.21145  36.65476     5
  n_composite 642.34106 661.15725 666.02819 662.99657 671.52093 692.12512     5

作为最后的评论:皮埃尔的方法和这里提出的解决方案之间存在许多解决方案。可以在numbers::Primes()循环中使用while,与n_composite()中发生的情况非常相似。也可以从“足够长”的整数序列开始,删除素数,然后取出剩下的第一个n个数。为了提高效率,这种方法需要在给定范围内很好地逼近素数的数量,这也不是微不足道的(对于低数字)。

答案 2 :(得分:0)

这确实是一种提出问题的懒惰方式,但是;这应该这样做:

is_composite<-function(x){
            sapply(x,function(y) if(y<3){FALSE}else{any(y%%(2:(y-1))==0)})
}
which(is_composite(1:100))

find_N_composites<-function(N){
    which(is_composite(1:(2*N+2)))[1:N]
}
find_N_composites(10)

system.time({
        x<-find_N_composites(1e+04)
})

这个想法是因此检查每个数字是否有除1和它本身之外的任何除数。我提供的功能在大约2秒钟内找到了前10 000个复合数字。如果你想要更大的速度,那么优化它会更好。例如,通过仅在简单数字中查找除数。