Difference between revisions of "Lucas number"

From Free Pascal wiki
Jump to navigationJump to search
m (→‎based on Fibonacci sequence: remove spelling mistake)
m (Reverted edits by Bart (talk) to last revision by Kai Burghardt)
(9 intermediate revisions by 2 users not shown)
Line 5: Line 5:
 
2, 1, 3, 4, 7, 11, 18, 29, 47, …
 
2, 1, 3, 4, 7, 11, 18, 29, 47, …
 
</syntaxhighlight>
 
</syntaxhighlight>
The idea is, that the next number is produced by summing the two previous ones.
+
The idea is, that the next number is produced by summing the two preceding ones.
  
 
== generation ==
 
== generation ==
The following implementations intends to just show the ''principle''.
 
They lack of input checking, thus has uncertain behavior when supplied with parameters out of range.
 
  
 
=== recursive implementation ===
 
=== recursive implementation ===
Line 27: Line 25:
 
   
 
   
 
\param n the index of the Lucas number to calculate
 
\param n the index of the Lucas number to calculate
\return the Lucas number at n
+
\return the Lucas number at n,
 +
        unless n is out of range, then 0
 
}
 
}
 
function lucas(const n: lucasLeftInverseRange): nativeUInt;
 
function lucas(const n: lucasLeftInverseRange): nativeUInt;
 
begin
 
begin
 
case n of
 
case n of
 +
// recursive case
 
2..high(n):
 
2..high(n):
 
begin
 
begin
 
lucas := lucas(n - 2) + lucas(n - 1);
 
lucas := lucas(n - 2) + lucas(n - 1);
 
end;
 
end;
 +
// base cases
 
1:
 
1:
 
begin
 
begin
Line 44: Line 45:
 
lucas := 2;
 
lucas := 2;
 
end;
 
end;
 +
// abort case
 
otherwise
 
otherwise
 
begin
 
begin
 +
// neutral element of addition
 +
// indicating n is out of range
 +
// [there is no n satisfying L(n) = 0]
 
lucas := 0;
 
lucas := 0;
 
end;
 
end;
Line 59: Line 64:
 
   
 
   
 
\param n the index of the Lucas number to calculate
 
\param n the index of the Lucas number to calculate
\return the Lucas number at n
+
\return the Lucas number at n,
 +
        unless n is out of range, then 0
 
}
 
}
 
function lucas(const n: lucasLeftInverseRange): nativeUInt;
 
function lucas(const n: lucasLeftInverseRange): nativeUInt;
 
begin
 
begin
if n > 0 then
+
case n of
begin
+
1..high(n):
lucas := fibonacci(n - 1) + fibonacci(n + 1);
+
begin
end
+
lucas := fibonacci(n - 1) + fibonacci(n + 1);
else
+
end;
begin
+
0:
// L(0) := 2
+
begin
lucas := 2;
+
// We can not deduce L(0) from Fibonacci
 +
// since that function is not defined for negative n
 +
// [we would call fibonacci(-1) + fibonacci(1)].
 +
lucas := 2;
 +
end;
 +
otherwise
 +
begin
 +
// neutral element of addition
 +
// indicating n is out of range
 +
// [there is no n satisfying L(n) = 0]
 +
lucas := 0;
 +
end;
 
end;
 
end;
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== iterative implementation ===
 +
This is in line with the [[Fibonacci number#iterative implementation|iterative implementation of <syntaxhighlight lang="pascal" enclose="none">fibonacci</syntaxhighlight>]] but with differing start values.
 +
Therefore the code is not repeated here.
  
 
== lookup ==
 
== lookup ==
Calculating Lucas numbers every time they are needed is time consuming.
+
Calculating Lucas numbers every time they are needed is time-consuming.
 
While the code required for generation takes almost no space, a lookup table is the means of choice when an application needs them a lot.
 
While the code required for generation takes almost no space, a lookup table is the means of choice when an application needs them a lot.
 
Since Lucas numbers can be derived from Fibonacci numbers, usually only one table (those with the Fibonacci series) is stored, being a compromise between efficiency and memory utilization.
 
Since Lucas numbers can be derived from Fibonacci numbers, usually only one table (those with the Fibonacci series) is stored, being a compromise between efficiency and memory utilization.
 +
In order to use the <syntaxhighlight lang="pascal" enclose="none">fibonacci</syntaxhighlight> table without margin case treatment, it has to be at least expanded to <syntaxhighlight lang="pascal" enclose="none">fibonacci[-1]</syntaxhighlight>.
  
 
An actual implementation is omitted here, since everyone wants it differently.
 
An actual implementation is omitted here, since everyone wants it differently.
 +
Also, do not program, what's already been programmed.
 +
For instance, the Lucas number functions of the [[gmp|GNU multiple precision arithmetic library]] take this approach.
  
 
== see also ==
 
== see also ==

Revision as of 20:34, 10 November 2018

English (en) suomi (fi) français (fr)

The Lucas series is the sequence of numbers:

2, 1, 3, 4, 7, 11, 18, 29, 47, 

The idea is, that the next number is produced by summing the two preceding ones.

generation

recursive implementation

 3type
 4	/// domain for Lucas number function
 5	/// where result fits within a nativeUInt
 6	// You can not name it lucasDomain,
 7	// since the Lucas number function itself
 8	// is defined for all whole numbers
 9	// but the result beyond L(n) exceeds high(nativeUInt).
10	lucasLeftInverseRange =
11		{$ifdef CPU64} 0..92 {$else} 0..46 {$endif};
12
13{**
14	calculates Lucas number recursively
15 
16	\param n the index of the Lucas number to calculate
17	\return the Lucas number at n,
18	        unless n is out of range, then 0
19}
20function lucas(const n: lucasLeftInverseRange): nativeUInt;
21begin
22	case n of
23		// recursive case
24		2..high(n):
25		begin
26			lucas := lucas(n - 2) + lucas(n - 1);
27		end;
28		// base cases
29		1:
30		begin
31			lucas := 1;
32		end;
33		0:
34		begin
35			lucas := 2;
36		end;
37		// abort case
38		otherwise
39		begin
40			// neutral element of addition
41			// indicating n is out of range
42			// [there is no n satisfying L(n) = 0]
43			lucas := 0;
44		end;
45	end;
46end;

based on Fibonacci sequence

The Lucas numbers can be calculated by using the fibonacci function shown in the article Fibonacci number.

54{**
55	calculates Lucas number based on Fibonacci numbers
56 
57	\param n the index of the Lucas number to calculate
58	\return the Lucas number at n,
59	        unless n is out of range, then 0
60}
61function lucas(const n: lucasLeftInverseRange): nativeUInt;
62begin
63	case n of
64		1..high(n):
65		begin
66			lucas := fibonacci(n - 1) + fibonacci(n + 1);
67		end;
68		0:
69		begin
70			// We can not deduce L(0) from Fibonacci
71			// since that function is not defined for negative n
72			// [we would call fibonacci(-1) + fibonacci(1)].
73			lucas := 2;
74		end;
75		otherwise
76		begin
77			// neutral element of addition
78			// indicating n is out of range
79			// [there is no n satisfying L(n) = 0]
80			lucas := 0;
81		end;
82	end;
83end;

iterative implementation

This is in line with the iterative implementation of fibonacci but with differing start values. Therefore the code is not repeated here.

lookup

Calculating Lucas numbers every time they are needed is time-consuming. While the code required for generation takes almost no space, a lookup table is the means of choice when an application needs them a lot. Since Lucas numbers can be derived from Fibonacci numbers, usually only one table (those with the Fibonacci series) is stored, being a compromise between efficiency and memory utilization. In order to use the fibonacci table without margin case treatment, it has to be at least expanded to fibonacci[-1].

An actual implementation is omitted here, since everyone wants it differently. Also, do not program, what's already been programmed. For instance, the Lucas number functions of the GNU multiple precision arithmetic library take this approach.

see also