| Die Berechnung der Quadratwurzel nach Heron ist eines der ältesten dokumentierten Iterations-Verfahren. Man kann es noch heute verwenden, wenn keine mathematischen Funktionen zur Verfügung stehen, oder um in Mikroprozessor-Anwendungen Zeit zu sparen. | In der IT-Ausbildung ist das Beispiel gut verwendbar, weil der Algorithmus besonders einfach ist, und man das Ergebnis mit der Standard Wurzel-Funktion kontrollieren kann. |
Algorithmen
|
Ausgewählte IT-Rezepte, Iterationen |
| Quadratwurzel | Die Quadratwurzel-Funktion in der Informatik |
| Heron | Berechnung der Quadratwurzel nach Heron |
Übungs- und Demo-Beispiel |
|
Live-Demo auf dieser Webseite |
|
Für einfache Mikroprozessoren |
|
| Optimierung | Beschleunigung eines Algorithmus für spezielle Anwendungen |
| Wurzel | Berechnung einer allgemeinen (beliebigen) Wurzel |
| Weitere Beispiele | Reihen-Entwicklung einiger ähnlicher / verwandter Funktionen |
Quadratwurzel |
|
|
Diese Funktion zählt zu jenen grundlegenden Funktionen, die in zahlreichen
Algorithmen vorkommen, und daher oft berechnet werden müssen. Alle ernstzunehmenden Programmiersprachen bieten Möglichkeiten zur Berechnung der Quadratwurzel-Funktion (mneist als SQR oder SQRT). Manchmal ist es notwendig, auch ohne mathematische Formeln auszukommen oder sie einfach, aber extrem schnell zu berechnen - für diese Fälle werden Reihen-Entwicklungen (Iterations-Verfahren) vorgestellt. Die Quadratwurzel ist jene Zahl, die - mit sich selbst multipliziert - ihr Argument ergibt:
y = sqrt(x)
y * y = x |
|
Die Quadratwurzel ist allerdings nur ein Sonderfall der allgemeinen Wurzel-Funktion
('n-te Wurzel'):
Quelle:
Wikipedia
Die Variable n kann nicht nur ganzzahlige Werte annehmen
(z.B. Quadratwurzel mit n=2, Kubikwurzel
mit n=3), sondern beliebige Gleitkomma-Werte.
|
Zur Berechnung allgemeiner Wurzeln kann man die Potenz-Funktion heranziehen (wenn sie verfügbar ist), oder → Logarithmus- und → Exponential-Funktionen, die man beide als Reihe entwickeln kann - in diesem Fall ausschließlich mit den 4 Grundrechnungs-Arten. |
Wurzel-Zeichen:(Rot bezeichnete Zeichen wurden Live von ihrem Browser erzeugt.)Unicode: Die Zeichen für n=2te, 3te und 4te Wurzel sind im Bereich 'Mathematical Operators' definiert: #221A (√), #221B (∛), #221C (∜) |
HTML: √ oder √ oder √ (√) ♦ Details zu Zeichen und Zeichen-Codes |
(Quadrat)-Wurzel in Programmiersprachen:Kalkulations-Programme (LibreOffice-Calc, OpenOffice-Calc, MS-Excel, ...): Die Standard-Funktion für ein Argument x in Zelle A1 lautet =WURZEL(A1) oder =A1^(1/2) Allgemeine Wurzeln mit dem Argument n in Zelle A2 berechnet man mit =A1^(1/A2)
C / C++ Man verwendet die Bibliothek #include <math.h>
und die Funktion
double sqrt (double x);
In C++ ist die Funktion u.a. mit den Typen float
und long double überladen.Diese Preprocessor-Makros sind meist definiert, werden jedoch als 'system-spezifisch' angegeben:
M_SQRT1_2 = 0.70710678118654752440
M_SQRT2 = 1.41421356237309504880 Java In der Klasse java.lang.Math ist die Funktion definiert: public static double sqrt(double x);
Javascript: Man verwendet ohne weitere Maßnahmen die Funktion y = Math.sqrt(x);
Javascript bietet u.a. diese Konstanten:
Math.SQRT2 = 1.41421356237309504880
Math.SQRT1_2 = 0.70710678118654752440 |
Perl Die Standard-Funktion lautet y = sqrt(x);
Das Modul Math::Complex bietet darüber hinaus
Unterstützung für komplexe Zahlen.PHP Die Standard-Funktion lautet y = sqrt(x);
PHP bietet u.a. diese
Konstanten:
M_SQRT1_2 = 0.70710678118655
M_SQRT2 = 1.4142135623731 M_SQRT3 = 1.7320508075689 M_SQRTPI = 1.7724538509055 SQL Die Standard-Funktion lautet y = sqrt(x);
Basic (LibreOffice-Basic, VBA) Die Standard-Funktion lautet y = Sqr(x)
♣
Beachten sie die unterschiedliche Behandlung optionaler Argumente in
LibreOffice- und Visual Basic
(VBA)→
Funktionen !XSLT Keine Quadratwurzel-Funktion: Muss bei Bedarf durch Reihenentwicklung selbst erstellt werden. |
Heron-Algorithmus |
||||||||||||||||||||||
| Dieses Iterations-Verfahren ('Babylonisches Wurzelziehen') wurde von Heron von Alexandria (ca. 1.Jahrhundert) entdeckt. Es liefert bereits nach wenigen Schritten erstaunlich gute Ergebnisse. | Heron war - wie viele Wissenschafter der Antike - vielfältig interessiert und außerordentlich produktiv. Ein Blick auf seine überlieferten Arbeiten lohnt sich ! | |||||||||||||||||||||
Heron-Algorithmus (Babylonisches Wurzelziehen)Start:
Das erste Element x[0] ist eine beliebige
→
Zufallszahl.Jedes weitere Element:
Quelle:
Wikipedia
|
Die Variablen a>=0 und x bezeichnen eine beliebige Zahl und ihre Quadratwurzel: x = sqrt(a)
Kontrolle: Das Quadrat der Wurzel muss wieder den Wert des
Arguments a ergeben:
x^2 = x * x = a
|
|||||||||||||||||||||
Kalkulations-ProgrammeDer Algorithmus ist so einfach, dass ihn selbst wenig geübte AnwenderInnen von Kalkulations-Programmen erstellen können.Voraussetzung: Man kann eine gegebene Formel in Anweisungen umsetzen - Für eine Programmiersprache oder wie hier für ein Kalkulations-Programm. ♣ Das Beispiel rechts zeigt nur die ersten 4 Elemente der Reihe. Füllen sie die Zellen A6:B6 bis zum Element 30 nach unten aus: Der Algorithmus erreicht dann in jedem Fall seinen Grenzwert = die Quadratwurzel der Zahl a in Zelle B1 |
Programmierung in einem Kalkulations-Programm:
• Die Werte in den Zellen B3...B6 sind die Ergebnisse der Methode nach dem 'Nullten', 1. und 2. Element. • Mit jeder zusätzlichen Zeile verbessert sich das Ergebnis. • Wenn die Grenze der Genauigkeit (des Kalkulations-Programms, nicht des Algorithmus) erreicht ist, dann ändert sich der berechnete Wert nicht mehr. • Mit Taste F9 wird eine neue Zufallszahl eingetragen und damit eine neue Berechnung ausgeführt. |
|||||||||||||||||||||
Programmierung mit Basic (LibreOffice-Basic, Visual Basic VBA)Argumente:
Die Funktion my_sqrt() akzeptiert 2 Argumente: a ... Zahl, deren Quadratwurzel zu berechnen ist nmax ... Maximale Anzahl der zu berechnenden Elemente. Wenn nmax nicht angegeben wird, dann rechnet das Programm bis zur maximalen Genauigkeit auf ≈ 15 Dezimalstellen. Anfangswerte:
doloop ... Schalter, steuert entweder die weitere Berechnung
oder den Abbruchx ... Ergebnis der Methode. Als erstes Element wird hier eine → Zufallszahl verwendet. n ... Zähler für die Elemente (Schritte) Schleife
In jedem Schleifen-Durchlauf wird 1 Element x der Reihe berechnet.Abbruch:
Das jeweils vorige Ergebnis xv wird mit dem aktuellen
Ergebnis x verglichen: Wenn keine Änderung erfolgt ist,
dann wird doloop=False gesetzt und damit die Schleife
abgebrochen.Zur Sicherheit oder zur schnelleren Rechnung wird die Schleife alternativ nach Berechnung der maximalen Anzahl von Elementen abgebrochen. |
Reihen-Entwicklung nach Heron als Basic-(VBA)Funktion:
Function my_sqrt( _
a As Double, _
Dim doloop As BooleanOptional nmax As Integer = -1) _ As Double Dim n As Integer Dim x, xv As Double
If nmax < 0 Then nmax = 1000
End Function
' If IsMissing(nmax) Then nmax = 1000
doloop = True' Anfangwerte x = Rnd n = 0 ' Schleife
While doloop
xv = x
Wendx = (x + a / x) / 2 If (x = xv Or n>=nmax) Then doloop = False n = n + 1 my_sqrt = x |
|||||||||||||||||||||
GeschwindigkeitDer Algorithmus ist ausgezeichnet und erreicht das Ziel (hier: die maximale Genauigkeit von 15 Dezimalstellen) bereits nach 10..20 Elementen. |
Durch geeignete Wahl des Anfangs-Werts x[0] kann man die Zahl der notwendigen Schritte stark verkürzen. ♦ Details bei der Vorstellung des ↓ Algorithmus in der Programmiersprache C/C++ aus dieser Seite. |
|||||||||||||||||||||
Programmierung mit JavascriptDie Funktion ist im Quelltext dieser Webseite enthalten und rechnet Live, wenn sie den Button klicken:
Live-Ergebnis:
Argument x = ?
my_sqrt(x) = ? sqrt_theor(x) = ? Genauigkeit ≈ ? Dezimalstellen Anzahl der Iterationen = ? Rechenzeit = ? µs |
Reihen-Entwicklung der Quadratwurzel als
Javascript-(JS)-Funktion.
function my_sqrt(a,nmax) {
if(nmax<0) {nmax=1000;}
}
var x = Math.random(); var xv = 0; var n = 0; doloop = true; while(doloop) {
xv = x;
}x = (x+a/x)/2; if(x==xv || n>=nmax) {doloop=false;} n++; return x; |
|||||||||||||||||||||
Quadratwurzel mit variabler Genauigkeit |
|
Programmierung mit C / C++Der Algorithmus wird in allen modernen Programmiersprachen ganz ähnlich formuliert. Das Beispiel rechts zeigt ein vollständiges C-Programm. Die Anwendung der Funktion ist im 'Haupt'-Programm main() rot bezeichnet.• Da → Zufalls-Daten ohne die Bibliothek <math.h> nicht zur Verfügung stehen, erfolgt die Initialisierung (Anfangs-Wert) von x mit einem beliebigen Wert - hier mit dem halben Wert des Arguments x=a/2 • Der 'eigentliche' Algorithmus wird innerhalb der Schleife wiederholt ausgeführt. Er ist im Beispiel rot bezeichnet. • In der Schleife wird zuerst der 'alte' Wert in der Variablen xv gespeichert, danach der neue Wert x berechnet. Aus dem Vergleich der beiden Werte ergibt sich der Fortschritt des Algorithmus in der jeweiligen Schleife. • Die Schleife wird beendet, wenn sich das berechnete Ergebnis nicht mehr ändert. Die Abbruch-Bedingung if(x==xv) ist einfach, jedoch nur dann anwendbar, wenn sich der berechnete Wert (so wie hier) dem theoretischen Ergebnis stetig nähert. • Wenn man das Verhalten des Algorithmus (noch) nicht genau kennt, dann begrenzt man die Schleife so wie hier mit einem Zähler (Variable n): Die Berechnung bricht mit Sicherheit nach n>nmax Schritten ab. Man testet das sorgfältig und entfernt danach die → Ausgabe (Funktion printf() ) aus der Funktion. |
Reihen-Entwicklung der Quadratwurzel als
C / C++-Funktion, zunächst mit maximaler Genauigkeit. Mini-Anwendung als
→
Konsolen-Programm: Bibliothek und Deklaration:
#include <stdio.h>
Anwendung:
double my_sqrt(double);
int main() {
Funktion:
double x,y;
}
printf("Eingabe: x="); scanf("%lf",&x); y = my_sqrt(x);
printf("my_sqrt(%f)=%f\n",x,y);return 0;
double my_sqrt(double a) {
int doloop,n,nmax;
}
double x, xv; nmax = 1000; x = a / 2.0; n = 0; doloop = 1; while(doloop) {
xv = x;
}
x = (x+a/x) / 2.0;
if(x==xv || n>=nmax) {doloop=0;}n++; // printf("Abbruch nach %d Schritten\n",n);
return x;
|
Begrenzte GenauigkeitWenn man besonders rasch rechnen will, kann man auf Kosten der Genauigkeit Zeit sparen: Die rechts vorgestellte Variante der Funktion rechnet die Quadratwurzel auf 1% genau. Eine derartige Begrenzung ist u.a. für Mikroprozessoren sinnvoll, die Live (besonders schnell) rechnen sollen, und wo die sinnvolle Genauigkeit durch andere Faktoren (z.B. Mechanik einer Lenkung) vorgegeben ist.• Die Abbruch-Grenze wird mit der Variablen z eingestellt, hier auf 1% vom aktuellen Wert des Arguments a Alternativ (je nach Anwendung) kann man auch absolute Zahlenwerte als Grenze verwenden, z.B. z=0.01 • In der Schleife wird die Differenz d zwischen dem 'alten' (xv) und dem neuen (x) Ergebnis berechnet, danach ihr absoluter (positiver) Wert. • Die Schleife wird ausgeführt, solange while(d>z) die gewünschte Genauigkeit noch nicht erreicht ist. • Man muss die Variable d auf einen Anfangswert (hier d=x) setzen, damit die Schleife auf jeden Fall mindestens 1mal ausgeführt wird. |
Schneller rechnen mit begrenzter Genauigkeit, hier z.B. auf 1% des Arguments:
double my_sqrt(double a) {
double d,x,xv,z;
}x = a / 2.0; z = a / 100.0;
d = x;while(d>z) {
xv = x;
}x = (x+a/x) / 2.0; d = xv - x; if(d<0){d=-d;} return x; |
Optimierung:► Wenn man einen Algorithmus ohne Einschränkung allgemein anwenden will, dann folgt man am besten den publizierten Vorgaben.♣ Tipp: Verwenden sie seriöse Quellen. Webseiten für die Hausaufgaben von SchülerInnen zählen nicht immer dazu. ● In praktischen Anwendungen kann man fast immer Einschränkungen treffen. Wenn man sie geschickt ausnützt, kann man die allgemeinen Algorithmen meist vereinfachen und beschleunigen. Beispiel: Wenn man in der Praxis nur die Quadratwurzeln von Werten 10..a..20 auf maximal 5% genau berechnen will, dann kann man eine besonders schnelle Funktion (nur) genau für diese Anwendung programmieren. |
Ansatzpunkt ist meist die Anzahl der Schleifen: Man versucht, sie so gering wie möglich zu halten. Dazu hilft oft eine kluge Auswahl der Anfangswerte. Analyse: Sie müssen den Ablauf ihrer Funktion genau kennen. Fügen sie printf()-Funktionen zur → Ausgabe aller wichtigen Werte in die Funktion ein. Testen sie die Funktion mit den erwarteten Extremwerten (minimale und maximale Werte der Argumente) und mit typischen Argumenten (z.B. mit → Zufalls-Daten). Mit Geschick und Phantasie kann man die Funktion (nur!) für die getroffenen Einschränkungen verbessern. |
|
Anfangswert
Ein guter Anfangswert (hier x=a/2) reduziert die Anzahl
der notwenigen Schleifen-Durchgänge stark. Meist kennt man wenigstens die
Größenordnung des Arguments a:Beispiel Erwartungswert:
Wenn man die Wurzel des erwarteten Mittelwerts oder des am häufigsten
erwarteten Werts von a als konstanten Anfangs-Wert
verwendet, dann halbiert man ungefähr die Anzahl der notwendigen Schritte.Beispiel Dezimalstellen:
Wenn man (z.B. bei Eingabe des Arguments a als Text)
die Anzahl der Dezimalstellen vor dem Komma kennt, dann wählt man eine
Zufallszahl mit halb so vielen Dezimalstellen wie a als
Anfangs-Wert. Auch damit halbiert man ungefähr die Zahl der notwendigen Schritte.
|
Binär-System
Im →
Binärsystem kann man einige besondere Tricks anwenden. Das erfordert
allerdings die Programmierung in der Maschinensprache (Assembler) des jeweiligen
Prozessors.Die Multiplikation einer Zahl *2 bzw. die Division /2 wird durch Verschiebung ihres Bit-Musters um 1 Stelle nach links bzw. rechts durchgeführt. Diese Operation (shift) erfolgt weit schneller als jede andere Rechnung. Beispiel (Dezimal, hexadezimal, binär):
50.0 = 0x32 = b00110010
100.0 = 0x64 = b01100100 200.0 = 0xC8 = b11001000 |
Allgemeine Wurzel |
|||||||||||||||||||||||||||||||||||||
Das Heron-Verfahren lässt sich nicht nur auf die Quadratwurzel
anwenden, sondern in allgemeiner Form auf jede beliebige Wurzel.
Quelle:
Wikipedia
|
►
Man wählt einen beliebigen Anfangs-Wert y[0]
und berechnet daraus in jedem Schritt den nächsten Wert
y[1], y[2], ... - solange bis sich sich das Ergebnis nicht mehr
ändert, d.h. y[i-1]=y[i] ► Die Variable n gibt den 'Grad' der Wurzel an, d.h. für die 2.Wurzel (Quadratwurzel) ist n=2, für die 3.Wurzel (Kubikwurzel) ist n=3 usw. |
||||||||||||||||||||||||||||||||||||
Kalkulations-ProgrammDer Algorithmus ist im Beispiel rechts bis zum 20. Element ausgeführt.Bei Erfolg ergibt die Kontrolle in Zelle B4 den gleichen Wert wie die zu berechnende Zahl x in Zelle B1 Für die meisten Werte x funktioniert der Algorithmus bereits in dieser einfachen Form. Wenn das Ergebnis nicht konvergiert (=wenn die beiden letzten Zellen B26, B27 noch unterschiedliche Werte anzeigen, dann kann man mehr Elemente berechnen, oder einen besser passenden Anfangswert in B7 'raten'. |
Programmierung in einem Kalkulations-Programm (Daten für die 3. Wurzel
aus 123 eingetragen):
|
||||||||||||||||||||||||||||||||||||
|
Wie auch bei vielen anderen Algorithmen muss man die in der Literatur
(oder im Internet) angeführten Formeln mit großer Vorsicht
untersuchen und oft durch eigene Maßnahmen ergänzen: Die Variable n wird auf Werte n>=1 begrenzt. Alternativ könnte man für n<1 einen Fehler-Wert zurückgeben. Für negative Argumente x<0 und ungerade n wird ein Ergebnis berechnet. Dazu wird das Vorzeichen in der Variablen vz gespeichert und zuletzt wieder hinzugefügt. Für gerade n wird in diesem Fall ein Fehler-Wert zurückgegeben.. Danach folgt wie üblich die Initialisierung und die Berechnung des Algorithmus in einer Schleife. |
Basic (VBA) Funktion zur
Berechnung der n-ten Wurzel aus einer
Zahl x
Function my_root( _
x As Double, _
Dim doloop As BooleanOptional n As Integer = 2) _ As Double Dim i, imax, vz As Integer Dim y, yv As Double ' Tests und Sonder-Bedingungen
If n < 1 Then n = 1
' If IsMissing(n) Then n = 1
vz = 1If x < 0 Then
If n Mod 2 = 1 Then
End If
vz = -1
Elsex = -x Err.Raise 3001
End If
' Initialisierung
doloop = Truey = x / CDbl(n) imax = 100 i = 0 ' Schleife
While doloop
yv = y
Wendy = ((n - 1) * y ^ n + x) / (n * y ^ (n - 1)) If (y=y Or i>=imax) v Then doloop = False i = i + 1 my_root = vz * y |
||||||||||||||||||||||||||||||||||||