Java 斐波那契级数-递归求和
好的,我最初编写了一个简单的代码,根据用户输入从序列中返回斐波那契数 n=5将产生3Java 斐波那契级数-递归求和,java,math,recursion,fibonacci,Java,Math,Recursion,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)); } 我正在考虑修改代码以
static int fibonacci(int n) {
if (n == 1)
return 0;
else if (n == 2)
return 1;
else
return (fibonacci(n - 1) + fibonacci(n - 2));
}
我正在考虑修改代码以返回序列的和,而不仅仅是从序列中返回值。在尝试执行和时,我意外地在return语句中添加了1,令我惊讶的是,它正确地返回了和
对于n=5,下面的代码将返回7
我不确定这是不是一个正确的方法来计算总和
如果我加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,89144
我尝试了一些随机的n
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不,不会的。代码的第二个版本不计算斐波那契函数的所有值之和,直到给定值为止。基本情况也是错误的 如果要递归计算总和,请将问题分为两部分,如下所示:
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);
}
公共静态int fib(int n){
返回n<2?n:fib(n-1)+fib(n-2);
}
公共静态int-sumfib(int-n){
返回n<0?0:fib(n)+sumfib(n-1);
}
第一个函数计算fibonacci,第二个函数负责将值相加到给定的数字。您的代码需要测试
n您对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);
}
金额的对应代码为:
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);
}
作为删除的一部分,编译器/解释器通常会将尾部递归更改为一个简单的循环
你问:
如果我加1,我仍然无法计算出级数的总和是如何工作的。有人能解释一下吗
这个问题实际上是关于理解算法的,我想这是一个热门话题。但是,需要数学来描述该算法的工作原理。所以,这真的是一个数学问题。有一个问题。如果F[i]
是第i个Fibonacci数,S[n]
是第一个n
Fibonacci数的和,则上述定理说明:
S[n] = F[n+2] - 1
>如果我们通过定义<代码> s[n+1] < /代码>,
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[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
#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);
}
下面是一个归纳法证明,您的程序计算我在原始答案中提供的总和。让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
#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);
}
然后,您需要证明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
时等式成立,即:S[k+2]=F[k+2]+S[k+1]
S[k+2] = S[k+1] + S[k] + 1
=> S[k+2] = (F[k+1] + S[k]) + (F[k] + S[k-1]) + 1
=> S[k+2] = (F[k+1] + F[k]) + (S[k] + S[k-1] + 1)
=> S[k+2] = F[k+2] + S[k+1]
这就完成了证明。正确的方法是使用accumlator
代码应该是这样的(我没有检查它,只是想法)
递归是计算斐波那契数的一种非常低效的方法。在数字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;
}
//此方法将能够计算到F46,因为int不能保存
//更大的数字。您可以使用long类型计算到92,使用long类型计算到93
//C#中的无符号长字符。
专用int计算器选项(int num)
{
int-fnum=0;
int val1=0;
int val2=1;
for(int i=0;i0),则为else
{
fnum=val1+val2;
val1=val2;
val2=fnum;
}
}
返回fnum;
}
使用递归函数打印斐波那契级数的另一种方法
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
#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);
}
#包括
// 0 1 1 2 3 5 8 13...
//
void fibb(int idx,int curr=0,int next=0)
{
如果n=5,你的结果应该是11,而不是7。(1+2+3+5=11)。你到底想计算什么?我从0开始不是1…所以0+1+1+2+3…它对序列中的下一个数字有效吗?如果不,那么算法是错误的。它不是intfib(intn){返回n吗