Gibt es bekannte subquadratische Algorithmen zur Berechnung des Quadratwurzelbodens einer n
Bit-Ganzzahl?
Der naive Algorithmus wäre so etwas wie
def sqrt(x):
r = 0
i = x.bit_length() // 2
while i >= 0:
inc = (r << (i+1)) + (1 << (i*2))
if inc <= x:
x -= inc
r += 1 << i
i -= 1
return r
Dies erfordert O(n)
Iterationen, die jeweils O(n)
zeitliche Ergänzungen beinhalten , also ist es O(n^2)
insgesamt Zeit. Gibt es etwas schnelleres? Ich weiß, dass es für den Fall der Multiplikation spezielle Algorithmen gibt, die besser als die quadratische Zeit sind, aber ich kann nichts für Quadratwurzeln finden.
algorithms
numerical-algorithms
Antimon
quelle
quelle
Antworten:
Sie können die Newtonsche Methode oder eine Reihe anderer Methoden verwenden, um Annäherungen an Wurzeln des Polynoms .p ( x ) = x2- c
Die Konvergenzrate für die Newtonsche Methode ist quadratisch, was bedeutet, dass sich die Anzahl der korrekten Bits in jeder Iteration verdoppelt. Dies bedeutet, dass -Iterationen der Newtonschen Methode ausreichen.O ( lgn )
Jede Iteration der Newtonschen Methode wird berechnet
Die Bitkomplexität der Multiplikation ist O ( b lg b ) , um zwei b- Bit-Ganzzahlen zu multiplizieren (wobei lg lg b- Faktoren ignoriert werden). Die Bitkomplexität für die Division (auf b Bits der Genauigkeit) ist dieselbe. Daher kann jede Iteration in O ( n lg n ) -Operationen berechnet werden. Multipliziert man mit O ( lg n ) -Iterationen, so ergibt sich, dass die Gesamtlaufzeit zur Berechnung der Quadratwurzel mit n Genauigkeitsbits O ( n ( lg n) beträgtÖ ( b lgb ) b lglgb b Ö ( n lgn ) O ( lgn ) n . Dies ist subquadratisch.Ö ( n ( lgn )2)
Ich denke, eine genauere Analyse zeigt, dass dies auf die Laufzeit von O ( n lg n ) verbessert werden kann (indem berücksichtigt wird, dass wir jedes x j nur mit einer Genauigkeit von etwa j und nicht mit einer Genauigkeit von n kennen müssen ). . Selbst die grundlegendere Analyse zeigt jedoch bereits eine Laufzeit, die eindeutig subquadratisch ist.Ö ( n lgn ) xj j n
quelle
Eines der Probleme bei der Newtonschen Methode besteht darin, dass in jeder Iteration eine Divisionsoperation erforderlich ist, die die langsamste grundlegende Ganzzahloperation ist.
Newtons Methode für die reziproke Quadratwurzel tut dies jedoch nicht. Wenn die Zahl ist, für die Sie 1 finden möchtenx , iteriere:1x√
Dies wird oft ausgedrückt als:
Das sind drei Multiplikationsoperationen. Die Division durch zwei kann als Rechtsverschiebung implementiert werden.
Wir wissen, dass Newtons Methode die Anzahl der genauen signifikanten Stellen ungefähr verdoppelt. So können wir wählen:
Mit ein wenig Manipulation finden wir:
Bei jeder Iteration:
Dann:
Diese Analyse verbirgt jedoch ein wichtiges Prinzip, das jeder, der mit großen ganzen Zahlen arbeitet, berücksichtigen sollte: Da die Multiplikation in der Anzahl der Bits superlinear ist, sollten Multiplikationsoperationen nur mit ganzen Zahlen durchgeführt werden, die ungefähr die Größe der aktuellen Genauigkeit (und) haben Ich möchte hinzufügen, dass Sie versuchen sollten, Zahlen mit einer ähnlichen Größenordnung zu multiplizieren. Die Verwendung größerer Ganzzahlen ist eine Verschwendung von Aufwand. Konstante Faktoren sind wichtig, und für große ganze Zahlen sind sie sehr wichtig.
quelle