【发布时间】:2016-09-24 04:51:59
【问题描述】:
由于问题的复杂性很高,阶乘的递归计算应该很慢。 为什么我的基本实现不是很慢?我很好奇,因为这应该是一个糟糕方法的教科书示例。
是因为 C# 程序中的一些内部优化或缓存结果吗?
using System;
using System.Diagnostics;
using System.Numerics;
namespace FactorialRecursion
{
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
for (int i = 0; i < 4000; i++)
{
stopwatch.Reset();
stopwatch.Start();
Factorial(i);
stopwatch.Stop();
Console.WriteLine($"{i}! = ({stopwatch.Elapsed})");
}
Console.ReadKey();
}
static BigInteger Factorial(BigInteger number)
{
if (number <= 1)
return 1;
return number * Factorial(number - 1);
}
}
}
结果在这里:
3990! = (00:00:00.0144319)
3991! = (00:00:00.0149198)
3992! = (00:00:00.0159502)
3993! = (00:00:00.0116784)
3994! = (00:00:00.0104608)
3995! = (00:00:00.0122931)
3996! = (00:00:00.0128695)
3997! = (00:00:00.0131792)
3998! = (00:00:00.0142510)
3999! = (00:00:00.0145544)
【问题讨论】:
-
或者你有一个快速的处理器?
-
1) 调试它,或 2) 打印出阶乘的值,您可以自己查看。
-
对于输入 N,您正在执行 N 次乘法运算。为什么不快呢?
-
“我很好奇,因为这应该是教科书上一个糟糕方法的例子。”您是否可能将它与斐波那契混淆,其中非常幼稚的递归版本是 O(2^n) 时间复杂度?
-
如果您想检查缓存结果的想法,请尝试反转您的循环参数:从 4000 开始并向后工作。如果缓存是“罪魁祸首”,您会看到第一种情况的时间很长,4000!,而其他情况的时间很短。