我想要第一个'n'个连续的复合数
我搜索命令找到连续的复合数字,但我得到了结果证明了这个定理。我没有得到任何命令..请帮助我在R中解决这个问题。
答案 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个复合数字。如果你想要更大的速度,那么优化它会更好。例如,通过仅在简单数字中查找除数。