Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
循环真的比递归快吗? 根据我的教授,循环比使用递归更快,更缺乏,但我提出了用递归和循环计算Fibonacci级数的C++代码,结果证明它们非常相似。因此,我将可能的输入设为最大值,以查看性能是否有差异,并且出于某种原因,递归比使用循环的计时效果更好。有人知道为什么吗?提前谢谢_C++_Loops_Recursion - Fatal编程技术网

循环真的比递归快吗? 根据我的教授,循环比使用递归更快,更缺乏,但我提出了用递归和循环计算Fibonacci级数的C++代码,结果证明它们非常相似。因此,我将可能的输入设为最大值,以查看性能是否有差异,并且出于某种原因,递归比使用循环的计时效果更好。有人知道为什么吗?提前谢谢

循环真的比递归快吗? 根据我的教授,循环比使用递归更快,更缺乏,但我提出了用递归和循环计算Fibonacci级数的C++代码,结果证明它们非常相似。因此,我将可能的输入设为最大值,以查看性能是否有差异,并且出于某种原因,递归比使用循环的计时效果更好。有人知道为什么吗?提前谢谢,c++,loops,recursion,C++,Loops,Recursion,代码如下: #include "stdafx.h" #include "iostream" #include <time.h> using namespace std; double F[200000000]; //double F[5]; /*int Fib(int num) { if (num == 0) { return 0; } if (num == 1) { return 1; }

代码如下:

#include "stdafx.h"
#include "iostream"
#include <time.h>
using namespace std;

double F[200000000];
//double F[5];

/*int Fib(int num)
{
    if (num == 0)
    {
        return 0;
    }

    if (num == 1)
    {
        return 1;
    }

    return Fib(num - 1) + Fib(num - 2);

}*/

double FiboNR(int n) // array of size n
{


    for (int i = 2; i <= n; i++)
    {
        F[i] = F[i - 1] + F[i - 2];
    }
    return (F[n]);
}

double FibMod(int i,int n) // array of size n
{
    if (i==n)
    {
        return F[i];
    }

    F[i] = F[i - 1] + F[i - 2];
    return (F[n]);
}

int _tmain(int argc, _TCHAR* argv[])
{
    /*cout << "----------------Recursion--------------"<<endl;
    for (int i = 0; i < 36; i=i+5)
    {
        clock_t tStart = clock();
        cout << Fib(i);
        printf("Time taken: %.2fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
        cout << " : Fib(" << i << ")" << endl;
    }*/

    cout << "----------------Linear--------------"<<endl;
    for (int i = 0; i < 200000000; i = i + 20000000)
    //for (int i = 0; i < 50; i = i + 5)
    {
        clock_t tStart = clock();
        F[0] = 0; F[1] = 1;
        cout << FiboNR(i);        
        printf("Time taken: %.2fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
        cout << " : Fib(" << i << ")" << endl;
    }

    cout << "----------------Recursion Modified--------------" << endl;
    for (int i = 0; i < 200000000; i = i + 20000000)
    //for (int i = 0; i < 50; i = i + 5)
    {
        clock_t tStart = clock();
        F[0] = 0; F[1] = 1;
        cout << FibMod(0,i);
        printf("Time taken: %.2fs\n", (double)(clock() - tStart) / CLOCKS_PER_SEC);
        cout << " : Fib(" << i << ")" << endl;
    }

    std::cin.ignore();
    return 0;
}
#包括“stdafx.h”
#包括“iostream”
#包括
使用名称空间std;
双F[200000000];
//双F[5];
/*int Fib(int num)
{
如果(num==0)
{
返回0;
}
如果(num==1)
{
返回1;
}
返回Fib(num-1)+Fib(num-2);
}*/
双FiboNR(int n)//大小为n的数组
{

对于(int i=2;i你可以使用传统的编程方法循环速度更快。但是有一类语言叫做函数式编程语言,它不包含循环。我是函数式编程的忠实粉丝,我是哈斯凯尔的狂热用户。哈斯凯尔是一种函数式编程语言。在这种语言中,你可以使用循环而不是循环e递归。要实现快速递归,有一种称为尾部递归的方法。基本上,为了防止系统堆栈中有大量额外信息,您可以编写函数,使所有计算都存储为函数参数,这样,除了函数调用poi外,不需要在堆栈中存储任何内容因此,一旦调用了最后一个递归调用,程序只需要转到第一个函数调用堆栈项,而不是展开堆栈。函数式编程语言编译器有一个内置的设计来处理这个问题。现在,即使是非函数式编程语言也在实现尾部递归

例如,考虑找到一个正数的阶乘的递归解。C中的基本实现是

int fact(int n)
{
  if(n == 1 || n== 0)
       return 1
   return n*fact(n-1);

}
在上述方法中,每次调用堆栈时,n都存储在堆栈中,以便它可以与事实结果(n-1)相乘。这基本上发生在堆栈展开期间。现在检查以下实现

int fact(int n,int result)
{
   if(n == 1 || n== 0)
       return result

       return fact(n-1,n*result);

}

在这种方法中,我们把计算结果传递给变量结果,因此最终我们直接得到变量结果的答案。你只需要在初始调用中传递一个值1,在这个例子中,栈可以直接解开到它的第一个入口。当然,我不确定C或C++允许。s尾部递归检测,但函数式编程语言可以。

我认为这不是一个好问题。但也许答案在某种程度上很有趣

首先让我说,一般来说,这句话可能是正确的。但是

<>关于C++程序性能的问题是非常本地化的。它永远不可能给出一个好的一般答案。每个例子都应该被分开分析。它涉及很多技术。C++编译器允许只要他们不产生明显的副作用,就可以根据实际情况修改程序。(不管这到底意味着什么)。只要你的计算给出相同的结果就可以了。这在技术上允许你将一个版本的程序转换成一个等价的版本,甚至从递归版本转换成基于循环的版本,反之亦然。所以这取决于编译器的优化和编译器的努力

此外,要将一个版本与另一个版本进行比较,您需要证明所比较的版本实际上是等效的

如果算法的递归实现比基于循环的算法更容易为编译器优化,那么它也可能以某种方式比基于循环的算法更快。通常迭代版本更复杂,通常代码越简单,编译器就越容易优化,因为它可以对不变量等进行假设。

“递归修改”版本根本没有递归

事实上,启用非递归版本只填充数组的一个新条目的唯一方法是主函数中的for循环——因此它实际上也是一个使用迭代的解决方案(注意到这一点,请向immibis和blastfurne致意)

但是您的版本甚至没有正确执行此操作。相反,由于它总是使用
i==0
调用,因此它非法读取
F[-1]
F[-2]
。您很幸运(?)1程序没有崩溃

您得到正确结果的原因是整个
F
数组的前缀是正确的版本

您尝试计算Fib(2000…)无论如何都不会成功,因为您溢出了一个
double
。您是否尝试运行该代码

这是一个正确工作的版本(无论如何,精确到
double
),并且不使用全局数组(它实际上是迭代与递归,而不是迭代与记忆)

#包括
#包括
#包括
双纤维致畸剂(int n)
{
双a=0.0,b=1.0;

如果(n)请在问题中包含问题引用的代码,这样我们就可以在不访问其他站点的情况下看到它。只是一个猜测,但您可能已经得到了编译为优化尾部调用递归“更差”的东西?这对我来说是一个罕见的描述。介意详细说明吗?你可能会注意到
FibNR
FibMod
都不使用递归。事实上它们做的事情不同!
FibNR
计算到给定点的所有斐波那契数,而
FibMod
只计算其中一个(假设所有剩余的都已经计算过)斐波那契递归(没有)由于组合爆炸,C和C++都允许检测,在ASIF规则下,但不需要编译器将尾递归转换为迭代。谢谢,让我知道非常有趣的是,这正是我所要寻找的方法。
#include <cstdio>
#include <ctime>
#include <utility>


double FiboIterative(int n)
{
    double a = 0.0, b = 1.0;

    if (n <= 0) return a;

    for (int i = 2; i <= n; i++)
    {
        b += a;
        a = b - a;
    }
    return b;
}

std::pair<double,double> FiboRecursive(int n)
{
    if (n <= 0) return {};

    if (n == 1) return {0, 1};

    auto rec = FiboRecursive(n-1);

    return {rec.second, rec.first + rec.second};
}

int main(void)
{
    const int repetitions = 1000000;
    const int n = 100;
    volatile double result;

    std::puts("----------------Iterative--------------");
    std::clock_t tStart = std::clock();
    for( int i = 0; i < repetitions; ++i )
        result = FiboIterative(n);
    std::printf("[%d] = %f\n", n, result);
    std::printf("Time taken: %.2f us\n", (std::clock() - tStart) / 1.0 / CLOCKS_PER_SEC);

    std::puts("----------------Recursive--------------");
    tStart = std::clock();
    for( int i = 0; i < repetitions; ++i )
        result = FiboRecursive(n).second;
    std::printf("[%d] = %f\n", n, result);
    std::printf("Time taken: %.2f us\n", (std::clock() - tStart) / 1.0 / CLOCKS_PER_SEC);
    return 0;
}