Subsections


8 Noch eine Berechnungsmethode für Fibonaccizahlen

Auf die folgende Berechnungsmethode bin ich gestoßen, als ich die Eigenschaften von $ \lambda$ näher untersucht habe. Dabei dürfte ich wohl ein mir bisher unbekanntes Verfahren »wiederentdeckt« haben.7 Vielleicht ist die Herleitung aber interessant:

Betrachten wir das charakteristische Polynom x2 - x - 1. Nullsetzen ergibt x2 = x + 1. Die Nullstellen sind $ \lambda$ und $ \mu$. Für diese gilt x2 = x + 1.

Für x3 erhalten wir daraus x3 = x2 . x = (x + 1) . x = x2 + x = (x + 1) + x = 2x + 1 = F3 . x + F2; analog ergibt sich induktiv

xn = xn-1 . x = (Fn-1 . x + Fn-2) . x = Fn-1 . x2 + Fn-2 . x = Fn-1 . (x + 1) + Fn-2 . x

= Fn-1 . x + Fn-1 + Fn-2 . x = (Fn-1 + Fn-2) . x + Fn-1 = Fn . x + Fn-1

Mit diesem Wissen können wir die geschlossene Form auch einfach ausrechnen:

$\displaystyle {\frac{{\lambda^{n}-\mu^{n}}}{{\lambda-\mu}}}$ = $\displaystyle {\frac{{(F_{n}\cdot\lambda+F_{n-1})-(F_{n}\cdot\mu+F_{n-1})}}{{\lambda-\mu}}}$ = $\displaystyle {\frac{{F_{n}\cdot(\lambda-\mu)}}{{\lambda-\mu}}}$ = Fn

ebenso:

$\displaystyle \lambda^{{n}}_{}$ + $\displaystyle \mu^{{n}}_{}$ = (Fn$\displaystyle \lambda$ + Fn-1) + (Fn$\displaystyle \mu$ + Fn-1) = Fn . ($\displaystyle \lambda$ + $\displaystyle \mu$) + 2Fn-1 = Fn . ($\displaystyle {\frac{{1+\sqrt{5}}}{{2}}}$ + $\displaystyle {\frac{{1-\sqrt{5}}}{{2}}}$) + 2Fn-1

= Fn +2Fn-1 = Fn + Fn-1 + Fn-1 = Fn+1 + Fn-1 = Ln


8.0.0.1 Eine neue Struktur

Kennen Sie komplexe Zahlen? Ähnlich, wie man diese konstruiert, können wir auch hier vorgehen: Definiere a : = (a1, a2) : = a1 . $ \lambda$ + a2; analog sei b : = (b1, b2) : = b1 . $ \lambda$ + b2.

Die Definition eines solchen Zahlenpaares ist in dem Sinne eindeutig, dass es eine reelle Zahl darstellt, welche nicht durch ein anderes Paar aus rationalen (und daher erst recht nicht natürlichen) Zahlen gebildet werden kann. Denn sei z.B. a = b, also a1 . $ \lambda$ + a2 = b1 . $ \lambda$ + b2, dann folgt (a1 - b1) . $ \lambda$ = b2 - a2, womit die rechte Seite der Gleichung entweder null oder ebenfalls irrational sein muß.

Mit obiger Definition gelten folgende Rechenregeln:

a + b = (a1, a2) + (b1, b2) = (a1$\displaystyle \lambda$ + a2) + (b1$\displaystyle \lambda$ + b2) = (a1 + b1)$\displaystyle \lambda$ + (a2 + b2) = (a1 + b1, a2 + b2)

a . b = (a1, a2) . (b1, b2) = (a1$\displaystyle \lambda$ + a2)(b1$\displaystyle \lambda$ + b2) = a1$\displaystyle \lambda$b1$\displaystyle \lambda$ + a1$\displaystyle \lambda$b2 + a2b1$\displaystyle \lambda$ + a2b2

= a1b1$\displaystyle \lambda^{{2}}_{}$ + (a1b2 + a2b1)$\displaystyle \lambda$ + a2b2 = a1b1($\displaystyle \lambda$ +1) + (a1b2 + a2b1)$\displaystyle \lambda$ + a2b2

= a1b1$\displaystyle \lambda$ + a1b1 + (a1b2 + a2b1)$\displaystyle \lambda$ + a2b2 = (a1b1 + a1b2 + a2b1)$\displaystyle \lambda$ + a1b1 + a2b2

= (a1b1 + a1b2 + a2b1, a1b1 + a2b2)

In dieser Struktur kann man also »addieren« und »multiplizieren«. Wir stellen fest, daß $ \lambda^{{0}}_{}$ = 1 = (0, 1), $ \lambda^{{1}}_{}$ = $ \lambda$ = (1, 0), $ \lambda^{{2}}_{}$ = $ \lambda$ + 1 = (1, 1) und allgemein gilt: $ \lambda^{{n}}_{}$ = Fn . $ \lambda$ + Fn-1 = (Fn, Fn-1). Dies liefert uns ein Verfahren, um (Fn, Fn-1) durch schnelle Exponentiation (durch fortgesetztes Quadrieren mit anschließendem Zusammenmultiplizieren der zu den Zweierpotenzen gehörigen Quadrate) zu bestimmen. Die Lösung für allgemeine Fibonaccifolgen ergibt sich dann mittels 4.1.2.


\begin{algorithm}
% latex2html id marker 1676
[th]
\par
\caption{
Fibonaccizahle...
...~(r1{*}x1+r2{*}x2,r2{*}x1+(r1-r2){*}x2);
\par
end;\end{list}\par
\end{algorithm}

8.0.0.2 Algorithmus

Der Algorithmus cap:ExpoAlgorithmus erwartet ein Fibonaccizahlenpaar x : = (f1, f0) mit den Startwerten der Fibonaccifolge sowie den Index n und liefert dann das Paar (fn, fn-1) als Ergebnis zurück.

8.0.0.2.1 Bemerkungen:

  1. Der Ausdruck (n and i) steht für den komponentenweisen and-Operator: Genau diejenigen Bits, die sowohl in n als auch in i gesetzt sind, sind auch im Ergebnis gesetzt. Der Ausdruck ist genau dann als wahr zu interpretieren, wenn mindestens ein Bit im Ergebnis gesetzt ist.
  2. Für r . q kommt man mit drei skalaren Multiplikationen aus, wenn man h1 : = (r1 + r2)(q1 + q2) = r1 . q1 + r1 . q2 + r2 . q1 + r2 . q2; h2 : = r1 . q1; h3 : = r2 . q2 setzt. Es ergibt sich (r1 . q1 + r1 . q2 + r2 . q1, r1 . q1 + r2 . q2) = (h1 - h3, h2 + h3).
  3. Die Anzahl der erforderlichen Multiplikationen für q . q kann man auf zwei reduzieren, in dem man die Lucasfolge verwendet: h1 : = q1 + 2 . q2 = Fi +2Fi-1 = Li; h2 : = h1 . h1 - (- 1)i . 2 = Li2 - (- 1)i . 2 = L2i; h3 : = q1 . h1. Es ergibt sich (q1 . q1 + 2 . q1 . q2, q1 . q1 + q2 . q2) = (F2i, F2i-1) = (Fi . Li,$ {\frac{{L_{2i}-F_{2i}}}{{2}}}$) = (h3,$ {\frac{{h2-h3}}{{2}}}$).
  4. Wird die Funktion häufig und mit vielen verschiedenen Werten aufgerufen8, so kann man die Quadrate vorab berechnen und in einem Array speichern.

8.0.0.2.2 Ausblick:

Es geht noch schneller, wenn man die binäre Exponentiation ein wenig umgestaltet und vom höchstwertigen Bit abwärts verlaufen läßt; abhängig vom jeweiligen Bit ist dann entweder (F2i, F2i-1) oder (F2i+1, F2i) zu bestimmen. Dabei kommt man mit reinen Quadrierungsschritten aus und kann die Multiplikationen einsparen. Für jeden Schritt sind dann nur noch zwei skalare Quadrierungen sowie einige billige Operationen (Addition, Subtraktion, Shiften) erforderlich. Erläuterungen hierzu und eine Implementierung finden sich beispielsweise in [GNU MP]. - Solche »Exponentiationsalgorithmen« kann man auch allgemein betrachten und weiteren Optimierungen unterziehen (wobei sich wiederum ein Bezug zu den Fibonaccizahlen ergibt); siehe [PLMo92] für eine solche Untersuchung.

Thorsten Reinecke 2004-07-11