简体   繁体   English

斐波那契程序未完成执行

[英]Fibonacci program does not complete execution

Problem Description 问题描述

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms 通过考虑斐波那契数列中值不超过四百万的项,找到偶值项的总和

Program 程序

using System;

class fibonacci {
    // function to return Nth value of fibonacci
    public static long fibo_n(long N) {
        long fibon=0;
        switch (N) {
            case 1: fibon=1; break;
            case 2: fibon=2; break;
        }
        while(N>2) {
        fibon=fibo_n(N-1)+fibo_n(N-2);
        }
    return fibon;
    }
}    

class fibo_tester {
    static void Main() {
        int N=2;
        long sum=0;
        while(fibonacci.fibo_n(N) <= 13) {
            sum = sum + fibonacci.fibo_n(N);
            N=N+3;
        }
        Console.WriteLine("Sum is {0}: ", sum);
    }
}

I reduced the number to 13 for testing instead of 4 million, but it still hangs. 我将测试的数量从原来的400万减少到13,但是仍然挂起。 Could someone please advise? 有人可以请教吗?

EDIT 2 编辑2

switch (N) {
        case 1: fibon=1; break;
        case 2: fibon=2; break;
        default: fibon=fibo_n(N-1)+fibo_n(N-2); break;
    }
 while(N>2) {
        fibon=fibo_n(N-1)+fibo_n(N-2);
        }

Is going to loop indefinitely, N is never updated in the loop. 无限循环,N永远不会在循环中更新。 You probably need to remove the While() clause and change it all to return fibo_n(N-1)+fibo_n(N-2); 您可能需要删除While()子句并将其全部更改以return fibo_n(N-1)+fibo_n(N-2); I'm not sure what you are doing with the switch statements, etc. But that should be a start. 我不确定您在使用switch语句等做什么。但这应该是一个开始。

I would actually replace it with this (if you want to use the switch): 我实际上将其替换为此(如果您想使用该开关):

class fibonacci
{
    // function to return Nth value of fibonacci
    public static long fibo_n(long N)
    {
        switch (N)
        {
            case 0:
                return 0;
            case 1:
                return 1;
            default:
                return fibo_n(N - 1) + fibo_n(N - 2);
        }
    }
}   

You might want to consider storing the values for each value of N in a dictionary or some sort of set so that you can look them up later. 您可能需要考虑将N的每个值的值存储在字典或某种类型的集合中,以便以后查找它们。 Since in your main program it seems like you are going to be looping over the values (successively larger N's that may have already been calculated). 由于在您的主程序中,您似乎将遍历这些值(可能已经计算出了较大的N)。 I'm not sure what the N+3 is about in your main loop, but you probably are going to miss something there (false assumption of the N-1, N-2 in the recursion perhaps?) 我不确定主循环中的N + 3是什么,但是您可能会错过那里的东西(递归中对N-1和N-2的错误假设?)

Also, if summing and dependent on your platform and how large of a value you test for (sicne your testing the sum of the first X Fibonacci numbers) you may have to use a ulong or find some other datatype that can handle larger numbers. 另外,如果求和并依赖于您的平台以及要测试的值的大小(测试您的第一个X斐波纳契数的总和),您可能必须使用ulong或查找一些可以处理更大数字的数据类型。 If I don't change everything from long to ulong on my system, the values wrap around. 如果我没有在系统上将所有内容从长久更改为冗长的内容,那么这些值就会回绕。 Fibonacci number can't be negative anyways, so why not use a ulong, or uint64 or something with more bits. 无论如何,斐波那契数不能为负,所以为什么不使用ulong或uint64或更多位。

You are using BOTH a loop AND recursion - you'll need to pick one or the other. 您同时使用循环和递归-您需要选择一个或另一个。 The problem spot in your code is here: 您的代码中的问题点在这里:

while (N>2) {
    fibon = fibo_n(N-1)+fibo_n(N-2);
}

In this spot the value of N never actually changes - that happens in the recursive step. 在这个位置上, N的值实际上不会改变-这是在递归步骤中发生的。 One example (not good) way to write this is: 编写此代码的一个示例(不好)方法是:

public static long fibo_n(long N) {
    if (N <= 0) return 0;
    if (N == 1) return 1;
    if (N <= 4) return N - 1;

    return fibo_n(N-1) + fibo_n(N-2);
}

Best of luck! 祝你好运!


Performance Note: 效果说明:

The reason this isn't a good approach is because function calls use memory in C# and they also take time. 这不是一个好方法的原因是因为函数调用使用C#中的内存,而且它们也需要时间。 Looping is always faster than recursion and in this case there isn't a good reason to solve this with recursion (as opposed to a simple loop). 循环总是比递归快,在这种情况下,没有充分的理由通过递归来解决这个问题(与简单的循环相反)。 I'll leave the code as is so you can compare to what you have, but I think you can find much better better code options elsewhere (although not all of these will be in C#). 我将代码保留不变,以便您可以与现有代码进行比较,但是我认为您可以在其他地方找到更好的更好的代码选项(尽管并非所有这些代码都在C#中)。

Let's say you call your method with N equal to 3. 假设您用等于3的N调用方法。

The switch doesn't do anything. 开关不执行任何操作。

N is greater than 2, so we go into the while loop. N大于2,因此我们进入while循环。 The while loop does something; while循环会执行某些操作; it computes a value, assigns it to fibon . 它计算一个值,并将其分配给fibon Then N, since it hasn't changed, is still greater than 2, so we compute it again. 然后,由于N不变,它仍然大于2,因此我们再次对其进行了计算。 It'll still be greater than two, so we compute it again. 它仍然会大于2,因此我们再次进行了计算。 We never stop computing it. 我们永远不会停止计算它。

Every time you assign a value to fibon you should instead be returning that value, because you're done; 每次为fibon分配一个值时,您应该返回该值,因为操作已经完成。 you have nothing left to compute. 您没有什么可计算的。 There's also no need for the while loop. 也不需要while循环。 You never need to execute that code more than once. 您永远不需要执行该代码一次以上。

Your implementation is also super inefficient. 你的实现也效率低下。 To compute fib(5) you compute fib(4) and fib(3). 要计算fib(5),请计算fib(4)和fib(3)。 To Then when computing fib(4) you compute fib(3) [again] and fib(2), when computing fib(3) both times they each compute fib(2) (so that's three times there), and if we do the math we end up seeing that you perform on the order of 2^n computations when computing fib(n). 然后在计算fib(4)时,再次计算fib(3)和fib(2),当两次计算fib(3)时,它们每次都计算fib(2)(因此是三倍),如果执行数学运算最终导致您在计算fib(n)时执行2 ^ n次计算。 On top of that , you're calling fib n times as you're counting up from zero in your main loop. 最重要的 ,您正在调用fib n次,因为您在主循环中从零开始计数。 That's tons and tons and tons of needless work re-computing the same values. 那就是无数次的工作和无数次的工作重新计算了相同的值。 If you just have a simple loop adding the numbers together as you go you can compute the result with on the order of N computations. 如果只有一个简单的循环将数字加在一起,则可以按N次计算的顺序来计算结果。

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

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