如何衡量循环和递归方法之间的代码速度差异?

时间:2013-02-09 02:42:45

标签: performance delphi loops recursion

假设我们必须创建一个计算器,它的第一个功能就是Fatorial。 我们可以将它写为递归函数或使用循环来获得结果。 我们都知道递归更慢,因为它具有指数性质。 但是如何通过代码而不是通过计算线来证明它?

我曾尝试计算花费的毫秒数,但是对于我的i7,它在初始时间和代码停止之间始终为零。

如何衡量循环和递归方法之间代码速度的差异?

type
  TJanela = class(TForm)
    Instrucao: TLabel;
    Entrada: TEdit;
    Botao: TButton;
    procedure Calcular(Sender: TObject);
  end;

var
  Janela: TJanela;
  Val, Fat, Start, TimeRecursive, TimeLoop: Int64;

function FR(N: Int64): Int64; // Fatorial Recursivo
function FL(N: Int64): Int64; // Fatorial em Loop

implementation

{$R *.dfm}

procedure TJanela.Calcular(Sender: TObject);
begin
  Val := StrToInt(Entrada.Text);
  Start := StrToInt(FormatDateTime('nnsszzz',Now));
  Fat := FR(Valor);
  TimeRecursive := StrToInt(FormatDateTime('nnsszzz',Now)) - Start;
  Start := StrToInt(FormatDateTime('nnsszzz',Now));
  Fat := FL(Valor);
  TimeLoop := StrToInt(FormatDateTime('nnsszzz',Now)) - Start;
  if Val > 25 then
    ShowMessage('Delphi can't calculate above [ 25! ]')
  else
    ShowMessage(' [ ' +
                IntToStr(Val) + '! ] is equal to [ ' +
                FormatFloat('###,###,###,###,###,###',Fat) + ' ]'#13#13+
                'Recursive: [ ' + IntToStr(TimeRecursive) + ' ] ms;'#13+
                'Loop: [ ' + IntToStr(TimeLoop) + ' ] ms;');
end;

function FR(N: Int64): Int64;
begin
  if N <= 1 then
    Result := 1
  else
    Result := N * FR(N - 1);
end;

function FL(N: Int64): Int64;
var
  I: Integer;
begin
  for I := 2 to N - 1 do
    N := N * I;
  if N = 0 then
    Result := 1
  else
    Result := N;
end;

既然大卫得到了答案,我在Mathematics上问了一个问题,这样他们就可以帮我推出两个方程式,以确定两种方法中给定阶乘将花费在计算机上的近似时间。 / p>

3 个答案:

答案 0 :(得分:8)

您正在使用相当低分辨率的计时器,并且对阶乘函数的单一评估太快甚至无法注册。

您可以使用更高分辨率的计时器,但到目前为止,最简单的方法是计算需要更长时间的计时器。而不是计算一次对阶乘的调用,时间为一千或一百万。

如果您真的对实现快速因子函数感兴趣,对于整数输入,那么您应该使用查找表。

对于它的价值,我认为诊断单元中的TStopWatch比日期/时间功能更方便定时。

答案 1 :(得分:5)

使用profiler。 Delphi的最新版本包括AQTime的有限功能版本,但此处搜索profiler Delphi此处会在StackOverflow处显示Profiler and Memory Analysis Tools for Delphi

Profilers允许您以几种不同的方式评估您的代码,包括执行其各个部分所花费的精确时间。您可以使用结果来确定哪个花费更多(或更少)时间。

答案 2 :(得分:0)

如果仅用于测试,你可以在循环之前放置一个TimeGetTime()而不是GetTime()。然后只需将值保存在列表框中即可查看需要多长时间。

如果太慢,请尝试QueryPerformanceCounter / QueryPerformanceFrequency