Schnelle Exponentiation

Mike Nöthiger
2 min readJan 29, 2020

a^x in O(log x) Multiplikationen berechnen.

Idee: a in jeder Iteration mit sich selber multiplizieren. So entsteht die Folge:

a^1
a^2
a^4
a^8
...

a^x kann nun berechnet werden, indem bestimmte Zahlen aus dieser Folge miteinander multipliziert werden. Es gilt nämlich:

a^(x+y) = a^x * a^y

Jede Dezimalzahl lässt sich als Summe von 2er Potenzen darstellen (Binärdarstellung). Beispiel:

27 = 2^0 + 2^1 + 2^3 + 2^4 = 1 + 2 + 8 + 16

a^27 könnte man dementsprechend wie folgt schreiben:

a^(1+2+8+16) = a^1 * a^2 * a^8 * a^16

Das sind alles Glieder aus der obig beschriebenen Folge. Wenn man also die richtigen Glieder aus der Folge miteinander multipliziert erhält man a^x. Mit einem Beispiel lässt sich wohl besser als mit Worten zeigen, wie diese Glieder selektiert werden:

27 in binär = 1011
1 a^1
1 a^2
0 a^4 (ignorieren)
1 a^8

Wenn wir also in jeder Iteration a mit sich selber multiplizieren entsteht automatisch die Folge a^1, a^2, a^4, ..., a^(2^n), und von denen multiplizieren wir alle die miteinander, wo in der Binärdarstellung vom Exponent eine 1 steht. Das ist insofern praktisch, als dass die Zahlen im Programmspeicher bereits als Binärzahlen vorliegen. Das kann man sich zunutze machen, die meisten Programmiersprachen bieten ein logisches UND & an, welches zwei Zahlen wie folgt verrechnet:

  1011 Zahl 1
& 0001 Zahl 2
= 0001 Resultat

Zugleich gibt es den Bitshift-Rechts Operator, der einfach alle Bits nach rechts schiebt:

1011 >> 1 = 0101

Diese zwei Mechanismen kombiniert man um herauszufinden, ob das aktuelle a^(2^n) Glied multipliziert werden muss:

1. Iteration: 1011 & 1 = 1 multiplizieren
2. Iteration: 0101 & 1 = 1 multiplizieren
3. Iteration: 0010 & 1 = 0 nichts tun
4. Iteration: 0001 & 1 = 1 multiplizieren
5. Iteration: 0000 & 1 = 0 (fertig wenn exponent 0 ist)

Folgend ein Beispiel Programm für die schnelle Exponentiation:

long res = 1;
while (x > 0) {
if (x & 1) {
res *= a;
}
x >>= 1;
a *= a;
}

Beim naiven Ansatz von a^x würden x Multiplikationen ausgeführt; a * a * a ... und das x mal. Bei der schnellen Exponentiation verdoppelt sich der Exponent in jedem Schritt (statt sich nur um 1 zu erhöhen), deshalb ist man bereits nach log2(x) Schritten bei x angelangt; 1, 2, 4, 8, log2(x)-4 weitere Schritte, x. Hinzu kommen die Multiplikationen mit dem Resultat, nämlich für jede 1 in der Binärdarstellung vom Exponent eine Multiplikation, also maximal log2(x) zusätzliche Multiplikationen (Exponent besteht aus lauter Einsen). Das macht Total 2*log2(x) Multiplikationen, damit ist die Berechnungskomplexität im Worst CaseO(log x).

--

--

Mike Nöthiger

Hi! 👋 I’m Mike — did you know the oldest computer was owned by Adam and Eve? It was an apple with very limited memory. Just one byte and everything crashed.