好的,我最初写了一个简单的代码,根据用户输入从系列中返回Fibonacci数字。
n = 5将产生3 ..
static int fibonacci(int n) {
if (n == 1)
return 0;
else if (n == 2)
return 1;
else
return (fibonacci(n - 1) + fibonacci(n - 2));
}
我正在考虑修改代码以返回系列的总和,而不是仅仅返回系列中的值,并且在尝试执行总和时我意外地将1添加到return语句中,令我惊讶的是,它返回了总和正确。
以下代码将返回7,n = 5.
我不确定这是否是计算总和的正确方法......
如果我加1,我仍然无法弄清楚该系列的总和是如何工作的。有人可以解释一下吗?
static int fibonacci(int n) {
if (n == 1)
return 0;
else if (n == 2)
return 1;
else
return (fibonacci(n - 1) + fibonacci(n - 2)+(1));
}
编辑:
斐波那契系列.. 0,1,1,2,3,5,8,13,21,34,55,89,144 ....
我尝试了一些随机的
N = 13
该函数返回376
0 + 1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 + 55 + 89 + 144 = 376
N = 10
该函数返回88
0 + 1 + 1 + 2 + 3 + 5 + 8 + 13 + 21 + 34 = 88
答案 0 :(得分:10)
您对fibonacci
计划的修改确实可以计算总和。但是,使用递归的方式效率很低。处理此问题的一种方法是使用“动态编程”方法,其中计算值被缓存,以便第二次递归调用可以重用它们。但是,第n个斐波纳契数可以从基数计算出来。递归实现这将是:
public static int fib_r (int a, int b, int n) {
if (n == 1) return a;
if (n == 2) return b;
return fib_r(b, a+b, n-1);
}
public static int fib (int n) {
return fib_r(0, 1, (n > 0) ? n : 1);
}
总和的相应代码是:
public static int sumfib_r (int a, int b, int n) {
if (n == 1) return a;
if (n == 2) return b;
return sumfib_r(b, a+b+1, n-1);
}
public static int sumfib (int n) {
return sumfib_r(0, 1, (n > 0) ? n : 1);
}
尾部递归通常会被编译器/解释器更改为一个简单的循环,作为tail call删除的一部分。
你问:
如果我加1,我仍然无法弄清楚该系列的总和是如何工作的。有人可以解释一下吗?
这个问题实际上是关于理解算法,我认为这是SO的主题。但是,需要数学来描述算法的工作原理。所以,这真的是一个数学问题。有一个well known theorem regarding the sum of Fibonacci numbers。如果F[i]
是第i个斐波那契数,S[n]
是第一个n
斐波那契数的总和,那么上面的定理说明:
S[n] = F[n+2] - 1
因此,如果我们根据S[n+2]
的定义考虑,
S[n+2] = S[n+1] + F[n+2]
然后,用S[n] + 1
代替F[n+2]
:
S[n+2] = S[n+1] + S[n] + 1
您应该认识到的是“添加1个已修改的”fibonacci
功能。
以下是感应证明您的程序计算我在原始答案中提供的总和。让F
代表您的fibonacci
函数,让S
代表您的“添加1修改后的”fibonacci
函数。
F[1] = 0
F[2] = 1
F[i] = F[i-1] + F[i-2] for i > 1
S[1] = 0
S[2] = 1
S[i] = S[i-1] + S[i-2] + 1 for i > 1
然后,您需要一个k > 0
的证明:
k
.---
S[k] = > F[i]
`---
i = 1
请注意,当且仅当:
时,上述总和为真S[1] = F[1]
S[k] = F[k] + S[k-1] for k > 1
证据非常简单。基本情况很简单。
S[1] = F[1] = 0
S[2] = F[2] + F[1] = 1
S[3] = S[2] + S[1] + 1 = F[3] + F[2] + F[1] = 2
归纳步骤是:鉴于对于k > 2
的某些S[j+1] = F[j+1] + S[j]
,0 < j < k+1
,如果j = k+1
,则证明等式成立,即:{{1} }。
S[k+2] = F[k+2] + S[k+1]
这样就完成了证明。
答案 1 :(得分:3)
不,不会。代码的第二个版本不计算斐波那契函数的所有值的总和,直到给定值。基本情况也是错误的!
如果要递归计算总和,请将问题分成两部分,如下所示:
public static int fib(int n) {
return n < 2 ? n : fib(n-1) + fib(n-2);
}
public static int sumfib(int n) {
return n < 0 ? 0 : fib(n) + sumfib(n-1);
}
第一个函数计算fibonacci,第二个函数负责将值添加到给定数字。
答案 2 :(得分:1)
正确的方法是使用累加器。
代码应该看起来像这样(我没有检查它,这只是想法)
static int fibonacci(int n, int accumlator) {
if (n == 1)
return 0;
else if (n == 2)
return 1;
else
accumlator = (fibonacci(n - 1, accumlator) + fibonacci(n - 2, accumlator));
return accumlator;
}
答案 3 :(得分:0)
您的代码需要测试n<1
- 如果您传递0或更小的参数,它将永远持续......
除此之外 - 如果你致电fib(5)
,会发生以下情况:
...
return(fib(4) + fib(3))
fib(4):
return(fib(3) + fib(2))
fib(3):
return(fib(2) + fib(1))
now fib(2) == 1 by your definition, and fib(1) == 0
so fib(3) == 1
then fib(4) == 1 + 1 = 2
and fib(5) = fib(4) + fib(3) = 2 + 1 = 3
Now if you add the '+1', the following happens:
fib(1) and fib(2) are unchanged
fib(3) = 1 + 0 + 1 = 2
fib(4) = fib(3) + fib(2) + 1 = 4
fib(5) = fib(4) + fib(3) + 1 = 4 + 2 + 1 = 7
您的原始方法很好,但这取决于您如何考虑斐波纳契数的“顺序”(您希望第一个数字是什么)。
答案 4 :(得分:0)
递归是计算斐波纳契数的一种非常低效的方法。在数字43之后,它将花费超过30秒,直到你得到答案。我试着找出计算52号的时间,花了大约47分钟。所以时间增长得非常快。
递归代码:
private int calculateRecursivelyInt(int fnum)
{
if (fnum == 0)
return 0;
if (fnum == 1)
return 1;
return calculateRecursivelyInt(fnum - 1) + calculateRecursivelyInt(fnum - 2);
}
循环效率更高
//This method will be able to calculate till the F46 because int can't hold a
// bigger number. You can calculate till 92 with a type long and till 93 with
// unsigned long in C#.
private int calculateLoopInt(int num)
{
int fnum = 0;
int val1 = 0;
int val2 = 1;
for (int i = 0; i < num; i++)
{
if (num == 1)
fnum = 1;
else if (i > 0)
{
fnum = val1 + val2;
val1 = val2;
val2 = fnum;
}
}
return fnum;
}
答案 5 :(得分:0)
使用递归函数打印Fibonacci系列的另一种方法。
#include <iostream>
// 0 1 1 2 3 5 8 13...
//
void fibb (int idx, int curr = 0, int next = 0)
{
std::cout << curr << ", ";
if(!idx) return;
if(curr == 0) {
curr = 1;
fibb(--idx, curr, next);
return;
}
next += curr;
fibb(--idx, next, curr);
}
int main()
{
fibb(10);
}