【问题标题】:Fibonacci Sequence in RR中的斐波那契数列
【发布时间】:2018-07-11 23:43:55
【问题描述】:

我是一个新的 R 用户,编程经验非常有限,因此我的问题和代码写得不好。

我被分配了一个问题,我必须使用 while 循环来生成小于 4,000,000 的斐波那契数列的数字(斐波那契数列的特点是,前两个之后的每个数字都是前两个)。

接下来,我必须计算生成的序列中偶数的总和。

我的回复很成功,但是,我认为代码写得不是很好。我可以做得更好吗?

> x <- 0
> y <- 1
> z <- 0
if (x == 0 & y == 1) {
  cat(x)
  cat(" ")
  cat(y)
  cat(" ")
    while (x < 4000000 & y < 4000000) {
    x <- x + y
    cat(x)
    cat(" ")
    if (x %% 2 == 0) {
        z <- x + z
    }
    y <- x + y
    cat(y)
    cat(" ")
    if (y %% 2 == 0) {
        z <- y + z
    }
  }
}

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 P>

cat(z)

4613732

【问题讨论】:

  • @Terru_theTerror -- 该帖子与您声称重复的帖子无关。您链接的帖子是关于获得非常大的斐波那契数的不准确结果。这篇文章的准确性没有问题,甚至没有尝试达到几乎那么大的数字;他们只是在寻找对他们(已经有效且准确的)代码的改进。
  • 您可以使用 cat(x," ") 减少代码中“cat”的数量。

标签: r


【解决方案1】:

我会这样做。首先,我定义了一个全局变量i 来包含斐波那契数列的前两个元素。然后最后,我将全局变量重新分配给它的初始值(即 1)。如果我不这样做,那么当我再次调用函数fib(0,1) 时,输出不正确,因为它调用最后一个值为i 的函数。执行return() 以确保它不会在else 子句中返回任何内容也很重要。如果不指定return(),最终输出将是1,而不是斐波那契数列。

请注意,该系列仅持续到数字 13 (z&lt;14),显然您可以将其更改为您想要的任何内容。将其作为函数的第三个参数包含在内也是一个不错的选择,例如 fib(0,1,14)。试试看!

i <<- 1
fib <- function(x,y){
  z <- x+y
  if(z<14){
    if (i==1){
      i <<- i+1
      c(x,y,z,fib(y,z))
    }
    else c(z, fib(y,z))
  }
  else {
    i <<- 1
    return()
  }
}

a <- fib(0,1)
a

【讨论】:

    【解决方案2】:

    首先,cat 带有一个 sep 参数。您可以这样做 cat(x, y, sep = " ") 而不是为此使用 3 行。

    其次,当您调用while (x &lt; 4000000 &amp; y &lt; 4000000) 时,请注意y 将始终大于x,因为它是最后一个xy 的总和......所以检查@ 就足够了987654329@这里。

    对于 while 循环,您还可以使用计数器 - 可能更直观。不过,R 中的索引并没有那么快

    fib <- c(0, 1)
    i <- 2
    while (fib[i] < 4000000) {
      fib <- c(fib, fib[i-1] + fib[i])
      i <- i + 1
    }
    
    sum(fib[fib %% 2 == 0]) 
    

    如果你不一定需要while,你也可以通过递归来处理它

    fib <- function(x, y) {
      s <- x + y
      c(s, if (s < 4000000) fib(y, s))
    }
    
    f <- fib(0, 1)
    sum(f[f %% 2 == 0])
    

    【讨论】:

    • 我喜欢递归函数的方法。我建议将其修改为:fib &lt;- function(x = 0, y = 1) { s &lt;- x + y c(s, if (s + y &lt; 4000000) fib(y, s)) } 这样您就可以调用 fib() 而不是在调用本身中添加您的起始值,在您的示例中,您在传递 4000000 后获得第一个值,因此您可以将其更改为s + y &lt; 4000000
    【解决方案3】:

    首先,不需要将所有内容都显式打印出来。

    其次,在 R 中创建斐波那契数的向量然后求和更为惯用。如果您不知道斐波那契数的明确封闭形式,或者如果您被告知不要使用它,请使用循环来创建斐波那契数列。

    所以要构建斐波那契数列(一次两个),您可以这样做

    x <- 0
    y <- 1
    fib <- c()
    while (x < 4000000 & y < 4000000){
      x <- x + y
      y <- x + y
      fib = c(fib, x, y)
    }
    

    这将为您提供一个斐波那契数向量,包含所有小于 4000000 和更多的数(最后一个元素是 9227465)。

    然后运行

    sum(fib[fib %% 2 == 0 & fib < 4000000])
    

    得到结果。这将返回 4613732,就像您的代码一样。子集运算符[],当您在其中放入逻辑条件时,将仅输出满足逻辑条件的数字——在这种情况下,它们是偶数且小于 4000000。

    【讨论】:

      【解决方案4】:

      我正在使用here发现的斐波那契数列的封闭形式

      fib = function(n) round(((5 + sqrt(5)) / 10) * (( 1 + sqrt(5)) / 2) ** (1:n - 1))
      
      numbers <- 2
      while (max(fib(numbers)) < 4000000){ # try amount of numbers while the maximum of the sequence is less than 4000000
        sequence <- fib(numbers) # here the sequence that satisfies the "4000000 condition will be saved"
        numbers <- numbers + 1 # increase the amount of numbers
      }
      total_sum <- sum(sequence[sequence%%2==0]) # summing the even numbers
      

      【讨论】:

        猜你喜欢
        • 2015-06-05
        • 1970-01-01
        • 2020-01-18
        • 2013-08-03
        • 2014-05-19
        • 2015-08-30
        • 2013-03-14
        相关资源
        最近更新 更多