【问题标题】:Computation R program计算 R 程序
【发布时间】:2011-06-27 09:08:47
【问题描述】:

我想计算能被 1-20 的所有自然数整除的最小可能数;我在 R 中编写了以下程序,但没有得到所需的输出(似乎我的循环几乎永远不会结束)。

我的程序如下:

a = 21
c = 0
while ( c < 20){
    c = 0
    n = 1
    while ( n < 21 ){
        if (a%%n == 0) c = c + 1
        n = n+1
    }
    a = a + 1
}
print (a)

我哪里做错了?

【问题讨论】:

  • 好吧,你的外部循环while 的第一行将 c 重置为 0,所以它永远不会从外部循环中逃脱。
  • 使用有意义的变量名更容易阅读代码 -- 'a' 代表 'answer','c' 代表... ¿'count'?。 Andrie 是对的——如果你一直重置它,它永远不会破坏外循环。
  • @Andrie 如果所有a%%1:20==0 然后c 变为20 并且在c 重置为0 之前外循环中断。这样做有点奇怪,但它不是无限循环。
  • @SachaEpskamp 很好,谢谢。

标签: r infinite-loop


【解决方案1】:

这是一个更像 R 的解决方案,它利用这个事实,答案将是素数的乘积,p &lt;= 20,每个提升到一个索引 i 使得 p^i &lt;=20

sMult <- function(x)
# calculates smallest number that 1:x divides
{
    v <- 1:x
    require(gmp) # for isprime
    primes <- v[as.logical(isprime(v))]
    index <- floor(log(x)/log(primes))
    prod(rep(primes,index))
}

产量:

> sMult(20)
[1] 232792560
> sMult(20)%%1:20
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

虽然这个解决方案是通用的,但应该注意,对于大的xisprime 是概率性的。当然,当这可能给出错误的结果时,您也可能有一个大到无法准确存储的数字。幸运的是,gmp 包实现了一个大整数类bigz。要将此更改用于函数的最后一行:

prod(as.bigz(rep(primes,index)))

比较以下结果:

> sMult(1000)
[1] Inf
> sMult2(1000)
[1] "7128865274665093053166384155714272920668358861885893040452001991154324087581111499476444151913871586911717817019575256512980264067621009251465871004305131072686268143200196609974862745937188343705015434452523739745298963145674982128236956232823794011068809262317708861979540791247754558049326475737829923352751796735248042463638051137034331214781746850878453485678021888075373249921995672056932029099390891687487672697950931603520000"

【讨论】:

  • 那肯定是一个大整数!
【解决方案2】:

不清楚你在用nc做什么

这是一个重构的例程(我不知道 R 语法,所以你需要转换它,但逻辑仍然是相关的)

对于一个可以被所有 1..20 整除的数字,它也可以被所有

所以只需要测试 9699690 的倍数。

从 20 开始测试,这样循环会更快中断,网络迭代次数更少

你应该在 ans 上添加溢出检查,以防答案是 > ans 数据类型的最大值

ans = 9699690
Do
    Found = True
    For i = 20 To 2 Step -1
        If ans Mod i <> 0 Then
            Found = False
            ans = ans + 9699690
            Exit For
        End If
    Next
    If i < best Then best = i
    If Found Then Exit Do
Loop
Debug.Print ans

【讨论】:

  • Primes 是正确的选择。答案实际上是所有素数 p 提升到索引 i 使得 p^i gmp 的函数 isprime 可能有用.
【解决方案3】:

使用 Chris 的逻辑只测试大量 9699690 我可以找到答案:

found <- FALSE
test <- 9699690 

while(!found)
{
    test <- test + 9699690 
    found <- all(test%%(1:20)==0)
}

cat("The number is: ",test,"\n")
The number is:  232792560 

编辑:

至于为什么 OPs 代码不起作用,这可能是您感兴趣的而不是解决这个小难题,代码只有一个小问题,可能不是您喜欢的。如果我们在正确答案前输入一个值:

a = 232792559
c = 0 
while ( c < 20){     
    c = 0     
    n = 1     
    while ( n < 21 ){         
        if (a%%n == 0) c = c + 1         
        n = n+1     
    }     
    a = a + 1 
} 
print (a) 
[1] 232792561

我们得到一个太多了,这是因为即使答案是正确的,您也将1 添加到a。将它移到外循环的前面,它就可以工作了。它看起来就像一个无限循环,因为在 R 中计算这样的东西太慢了。在 R 中,我们需要做的事情与像 C 这样的语言不同,因为 R 代码没有被编译(意味着循环需要很长时间)并且针对矢量化输入进行了优化。

查看您的代码告诉我,您是 R 新手,但可能在其他语言方面经验丰富,但这种经验在 R 中对您没有太大帮助。我建议您阅读如何对事物进行矢量化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-12
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 2013-06-08
    • 2023-03-03
    相关资源
    最近更新 更多