Reputation: 9104
Let's say we have to create a calculator, and the first function it has is Fatorial. We can write it as a recursive function or use a loop to get the result. We all know that recursion is more slow because of it's exponential nature. But how to prove it by code and not by counting lines?
I have tried to calculate the amount of milliseconds spent, but with my i7 it is always zero between the initial time and when the code stops.
How can I measure the difference of speed of code between loop and recursive method?
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;
Now that David came with the answer, I asked a question on Mathematics so they can help me to come out with two equations to determine the proximate time a given factorial will spend on the computer in both methods.
Upvotes: 3
Views: 506
Reputation: 2593
if its just for testing, could you put a TimeGetTime() instead of GetTime() before the loop and one after. then just save the value in a list box to see how long it takes.
if that is too slow try QueryPerformanceCounter/QueryPerformanceFrequency
Upvotes: 0
Reputation: 613013
You are using quite a low resolution timer and a single evaluation of the factorial function is too fast to even register.
You could use a higher resolution timer, but by far the easiest approach is to time something that takes longer. Instead of timing a single call to factorial, time a thousand, or a million.
If you are actually interested in implementing a fast factorial function, for integer inputs, then you should use a lookup table.
For what it is worth, I think that TStopWatch in the Diagnostics unit is more convenient for timing than the date/time functions.
Upvotes: 8
Reputation: 125708
Use a profiler. Recent versions of Delphi include limited functionality versions of AQTime, but a search for profiler Delphi
here turns up Profiler and Memory Analysis Tools for Delphi here at StackOverflow.
Profilers allow you to evaluate your code in several different ways, including the precise amount of time spent executing various parts of it. You can use the results to determine which takes more (or less) time.
Upvotes: 5