Java 斐波那契级数-递归求和

Java 斐波那契级数-递归求和,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)); } 我正在考虑修改代码以

好的,我最初编写了一个简单的代码,根据用户输入从序列中返回斐波那契数

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));
    }
我正在考虑修改代码以返回序列的和,而不仅仅是从序列中返回值。在尝试执行和时,我意外地在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吗