简体   繁体   English

我无法理解这个Fibonacci程序流程

[英]I can't understand this Fibonacci program flow

so Im new to the world of programming and thought Id pick up a book to start learning. 所以我是编程和思想世界的新手,我会拿起一本书来开始学习。 I bought A Players Guide to C# 3rd Edition and one of the little homework assignments it gives you has me pretty stumped. 我买了C#3rd Edition的玩家指南和它给你的一个小作业,让我很难过。 I was debugging it step by step to help me understand, but the flow of the program makes no sense to me. 我一步一步地调试它以帮助我理解,但程序的流程对我来说毫无意义。 Here it is. 这里是。

      static void Main(string[] args)
        {
            for (int index = 1; index <= 10; index++)
            {
                Console.WriteLine(Fibonacci(index));
            }

            Console.ReadKey();
        }

        /// <summary>
        /// Returns a number from the Fibonacci sequence, starting at 1.
        /// Note that this implementation is not very optimized, and can
        /// take a very long time if you're looking up large numbers.
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        static ulong Fibonacci(int number)
        {
            if (number == 1) { return 1; }
            if (number == 2) { return 1; }

            return Fibonacci(number - 1) + Fibonacci(number - 2);
        }

the first two times it runs through the for loop it prints out '1' and '1' because the first time through the index is '1' making that first if statement true and the second time through the index is '2' making the second if statement true. 它通过for循环运行的前两次打印出'1'和'1',因为第一次通过索引是'1'使得第一个if语句为true而第二次通过索引是'2'使得第二个if语句为真。 But when it runs a 3rd time and the index turns to 3 it goes to that return statement, and if my math is right (3-1) + (3-2) equates to 3, which makes sense right. 但是当它第三次运行并且索引转到3时它转到那个return语句,如果我的数学是正确的(3-1)+(3-2)等于3,这是正确的。 So I expect it to break from the method return 3 and write that to the Console window, but it doesnt. 所以我希望它从方法返回3中断并将其写入控制台窗口,但它没有。 Instead it runs through the method again this time saying the value of the number is 2.(ok??) well at least it should stop at that 2nd if statement and reprint '1' again. 相反,这次再次运行该方法说这个数字的值是2.(好吧?)至少它应该停在第二个if语句并再次重新打印'1'。 Nope it ignores that line hits the return statement again. 不,它忽略了该行再次击中return语句。 What the hell is going on? 这到底是怎么回事? Please explain this logic. 请解释一下这个逻辑。

There is a nice illustration of this kind of recursive hell. 这种递归地狱有很好的例证。

Note that the illustration is for one iteration of your loop 请注意,该插图适用于循环的一次迭代

And also, it is drawn for this code : 此外,它是为此代码绘制的:

return Fibonacci(number - 2) + Fibonacci(number - 1);

as you have the reversed addition, the correct program flow would be the opposite as the one shown by the diagram below. 如果你有相反的添加,正确的程序流程将与下图所示的相反。

斐波纳契递归调用

Image was taken here : http://composingprograms.com/pages/28-efficiency.html 图片来自: http//composingprograms.com/pages/28-efficiency.html

I call it hell for two reasons : 我称它为地狱有两个原因:

Difficult to read for the developper 难以阅读开发人员

The first time the fib function is called, with parameter 6, it first calls fib(4), (the left part of the tree), then, when it's over, calls fib(5) (the right part of the tree). 第一次使用参数6调用fib函数时,它首先调用fib(4)(树的左侧部分),然后,当它结束时,调用fib(5)(树的右侧部分)。

Recursion can however be very useful for some case, but this school-one is absolutely not fitted for this recursion. 然而,递归对于某些情况可能非常有用,但是这个学校一个绝对不适合这种递归。 The purpose of code is not to be read only by compilers, it is to be read by developers as well. 代码的目的不是只由编译器读取,它也应由开发人员阅读。

Inefficient 低效

As you can see, some fib(n) are called several time with the same n. 正如您所看到的,一些fib(n)被称为具有相同n的多次。

At the end, this recursive algorithm is O(2^n) , which is quite bad for this problem 最后,这个递归算法是O(2 ^ n) ,这对这个问题非常不利

Even more inefficient in a loop 循环中效率更低

Remember, the illustration is for only one iteration ! 请记住,插图仅用于一次迭代! You can draw a diagram for fib(n) like this for each n. 你可以为每个n绘制一个这样的fib(n)图。

With this method, you lose each previously calculated values, instead of reusing them to calculate the next value. 使用此方法,您将丢失先前计算的每个值,而不是重复使用它们来计算下一个值。 This loop has then complexity O(n * 2^n) 这个循环具有复杂度O(n * 2 ^ n)

Well, it's a not so simple example of recursion, and to makes matters worst, it's being executed inside a loop... Hardly what I would use to teach people what recursion is. 好吧,这是一个不那么简单的递归示例,并且最糟糕的是,它正在循环中执行......我几乎不会用什么来教人们递归是什么。

So, the point of recursion is that a function will execute itself over and over again until it's stopping condition is met (And if it's never met or doesn't even exists it will create an infinite recursion, that most of the times is not a good thing). 因此,递归的重点是函数会一遍又一遍地执行,直到满足停止条件为止(如果它永远不会满足或者甚至不存在,它将创建一个无限递归,大多数时候不是好事)。

A classic example of recursion would be to calculate factorial (and in case you don't remember how it works, 5! = 5 * 4 * 3* 2 * 1). 递归的典型例子是计算阶乘(如果你不记得它是如何工作的,5!= 5 * 4 * 3 * 2 * 1)。

So an implementation of a factorial recursive method would be something like this: 因此,阶乘递归方法的实现将是这样的:

Int64 Factorial(int input)
{
    if(input < 0) 
    {
         throw new ArgumentOutOfRangeException("Input must be 0 or higher.");
    }
    if(input < 2) 
    {
        return 1;
    }
    return input * Factorial(input - 1);
}

(0! = 1, and -3! is invalid...) (0!= 1,-3!无效......)

Now, let's say you call this method with the number 3: 现在,假设您使用数字3调用此方法:
Factorial(3) will return 3 * Factorial(3-1) . Factorial(3)将返回3 * Factorial(3-1)
Similarly, Factorial(2) will return 2 * Factorial(2-1) . 同样, Factorial(2)将返回2 * Factorial(2-1)
Factorial(1) will simply return 1 . Factorial(1)将简单地返回1
Putting it all together Factorial(3) will return 3 * 2 * 1 which is 3! 综合因素Factorial(3)将返回3 * 2 * 13! .

Now, in your case, The Fibonacci recursive method stopping condition is number is either 1 or 2, but it calls itself twice: Fibonacci(number - 1) + Fibonacci(number - 2); 现在,在你的情况下, Fibonacci递归方法停止条件是数字是1或2,但它自己调用两次: Fibonacci(number - 1) + Fibonacci(number - 2); . To make matters worst it's being executed from inside a for loop, calculating the number on the Fibonacci sequences by indexes (from 1 to 10). 最糟糕的是,它是从for循环内部执行的,通过索引(从1到10)计算Fibonacci序列上的数字。

Let's examine what Fibonacci(3) does: 让我们来看看Fibonacci(3)作用:

Fibonacci(3) will return Fibonacci(3-1) + Fibonacci(3-2) . Fibonacci(3)将返回Fibonacci(3-1) + Fibonacci(3-2)
Fibonacci(2) will return 1 . Fibonacci(2)将返回1
Fibonacci(1) will return 1 . Fibonacci(1)将返回1

So, Fibonacci(3) will return 1 + 1. 所以, Fibonacci(3)将返回1 + 1。

Let's take the next number: 我们来看下一个数字:

Fibonacci(4) will return Fibonacci(4-1) + Fibonacci(4-2) . Fibonacci(4)将返回Fibonacci(4-1) + Fibonacci(4-2)
We already calculated that Fibonacci(3) returns 2, and we know that Fibonacci(2) will return 1, so Fibonacci(4) will return 3 我们已经计算出Fibonacci(3)返回2,我们知道Fibonacci(2)将返回1,所以Fibonacci(4)将返回3
(or 1+1+1 if you want to step into every call). (如果你想进入每个电话,则为1 + 1 + 1)。

Similarly, Fibonacci(5) will return Fibonacci(5-1) + Fibonacci(5-2) - So it's 3 + 2 and so on ( Fibonacci(6) will return 5+3, Fibonacci(7) will return 8+5). 同样, Fibonacci(5)将返回Fibonacci(5-1) + Fibonacci(5-2) - 所以它是3 + 2等等( Fibonacci(6)将返回5 + 3, Fibonacci(7)将返回8 + 5 )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM