| Logarithmus und Exponential sind wichtige Funktionen, u.a. weil sich damit viele aufwändige Rechnungen um eine Stufe vereinfachen. Wenn diese Funktionen nicht zur Verfügung stehen, dann kann man sie mit Reihen-Entwicklungen selbst programmieren. | Unabhängig davon sind die Beispiele für die Ausbildung gut brauchbar, weil man die Ergebnisse jederzeit durch Vergleich mit den Standard-Funktionen kontrollieren kann. |
Algorithmen
|
Ausgewählte IT-Rezepte, Iterationen |
| Log-Funktion | Die Ln() und Log()-Funktionen und ihre Anwendung in der Informatik |
| Anwendung | Multiplikation, Division, Potenzierung, Wurzeln, ... |
| Programmierung | Die Log-Funktion in Programmen und Programmiersprachen |
| Log-Reihe | Reihen-Entwicklung der Log-Funktion mit Live-Beispiel |
| Log-Algorithmus | Anpassung des Log-Algorithmus |
| Log-Optimierung | Optimierung des Log-Algorithmus |
| Basic | Log-Funktion mit LibreOffice-Basic, Visual Basic (VBA) |
| Javascript | Log-Funktion mit Javascript (z.B. Live in Webseiten) |
| Hilfs-Funktionen | Potenz-Funktion, Fakultät - nur mit den 4 Grundrechnungs-Arten |
| Verwandte Themen | Exponential-Funktion, Euler'sche Zahl e=2.71828... |
Logarithmus |
|
|
x = e^y
Die Umkehrung kann man als Potenzierung (hier mit dem
Operator ^ bezeichnet) oder mit Hilfe
der →
Exponential-Funktion beschreiben:
ln(x) = y x = exp(y)
● Als Basis wird die konstante → Euler'sche Zahl e=2.71828... verwendet. Das ergibt zwar keine anschaulichen Werte, man kann damit jedoch besonders gut rechnen. Der Funktions-Name wird meist LN, selten mit LOG abgekürzt. ♣ Der natürliche (und jede andere Logarithmus) ist nur für positive Zahlen>0 definiert, d.h. ln(0) oder ln(-1) ergeben Fehler. ♣ Sonderfall: ln(1) = 0
Beispiele:
ln(1/2) = -0.693147180559945
e^-0.693 = 2.718^-0.693 = 0.5 ln(2) = 0.693147180559945 e^0.693 = 2.718^0.693 = 2 ln(10) = 2.30258509299405 e^2.3026 = 2.718^2.3 = 10 |
|
|
Der Dekadische Logarithmus ist jene
Zahl y, mit der man die
Basis 10 potenzieren muss,
um eine Zahl x zu erhalten:
x = 10^y
log10(x) = y Die Zahl 10 als Basis ergibt anschauliche Werte. Deshalb wurde der dekadische Logarithmus in der Vor-Computer-Zeit von TechnikerInnen häufig verwendet. Umrechnung natürlicher ↔ dekadischer Logarithmus:
log10(x) = ln(x) / ln(10)
Umrechnungs-Faktor:
ln(x) = log10(x) * ln(10) ln(10) = 2.30258509299405
|
Beispiele:
log10(0.01) = -2
log10(0.1) = -1 log10(0.5) = -0.301029995663981 log10(1) = 0 log10(2) = 0.301029995663981 log10(e) = 0.434294481903252 log10(10) = 1 log10(100) = 2 log10(1000) = 3 |
|
Der Allgemeine Logarithmus verwendet eine beliebige
positive Zahl b>0 als Basis. Andere Basis-Werte
als b=e=2.718 oder b=10
haben jedoch geringe Bedeutung. Umrechnung:
log(b,x) = ln(x) / ln(b)
Der allgemeine Logarithmus ist die Umkehrung der allgemeinen Potenz-Funktion:
ln(x) = log(b,x) * ln(b)
y = pow(b,x) = b^x
Der Begriff y^(1/x) wird auch x-te Wurzel
aus y bekannt.
x = log(b,y) b = y^(1/x) |
Beispiele des allgemeinen Logarithmus mit der Basis b=2
log(2, 1/4) = -2
log(2, 1/2) = -1 log(2, 0) = 0 log(2, 2) = 1 log(2, 4) = 2 log(2, 8) = 3 2^3 = 8 |
ÄhnlichkeitDie Diagramme aller Logarithmus-Funktionen ln(), log10(), log(b,*) mit Basis 1>b sind einander ähnlich (so wie ↑ oben gezeigt), d.h. man kann sie durch Multiplikation der ln() Funktion mit einem konstanten Faktor erhalten.Diese Eigenschaft verwendet man zur Berechnung von Logarithmen mit beliebiger Basis mit Hilfe der fast immer verfügbaren ln() Funktion. (allgemeiner ↑ Logarithmus) |
SpiegelungDie Diagramme aller Logarithmus-Funktionen mit Basis 1<b erscheinen an der X-Achse gespiegelt.Daraus ergeben sich einige wichtige Eigenschaften der Funktion: ln(x) = -ln(1/x)
allgemein
log(b,x) = -log(1/b,x)
log(b,x) = -log(b,1/x) log(b,x) = log(1/b,1/x) |
Binär-SystemEinige wichtige Daten der Informatik kann man mit Potenzen und Logarithmen berechnen:Anzahl der mit b Bit darstellbaren positiven ganzen Zahlen d: d = 2^b
Beispiele:
1 Byte: 2^8 = 256
Um auch negative ganze Zahlen darzustellen, braucht man 1 Bit
für das Vorzeichen (Details zum
→ 2er-Komplement):
2 Byte: 2^16 = 65536 4 Byte: 2^32 = 4.295E+9 8 Byte: 2^64 = 1.845E+19
1 Byte: 2^(8-1) von -128 bis +127
Die Zahl 2^32 = 4.3E+9 wurde bekannt, weil damit
die 4GB-Grenze
von 32-Bit PC-Systemen erreicht wurde.2 Byte: 2^(16-1) von -32768 bis +32767 Umkehrung: Anzahl der benötigten Bits b zur Darstellung einer positiven ganzen Dezimalzahl d: b = ln(d) / ln(2)
Beispiele:
100: ln(100)/ln(2) = 6.6
Da es nur ganze Bits gibt, muss man die berechnete Anzahl b
immer aufrunden, um die angegebene Dezimalzahl d darzustellen:
256: ln(256)/ln(2) = 8.0 1000: ln(1000)/ln(2) = 9.97 Million: ln(1E+6)/ln(2) = 19.9 Milliarde: ln(1E+9)/ln(2) = 29.9 b = int(ln(d) / ln(2) + 0.5)
|
Gleitkomma-Zahlen werden in allen gängigen Programmen und Programmiersprachen ohne besondere Maßnahmen mit dem Typ → Double Precision gespeichert. Für diesen Typ werden 8 Byte = 64 Bit Speicherplatz verwendet, davon 53 Bit für die binäre Mantisse und 11 Bit für den binären Exponenten. ● Die binäre Mantisse bestimmt die Genauigkeit (Auflösung) der Zahlen: 2^53 = 9E+15, d.h. die mit 53 Bit erreichbare Genauigkeit beträgt ca. 15..16 Dezimalstellen. Test mit einem Kalkulations-Programm oder mit Double Precision-Variablen einer beliebigen Programmiersprache: Berechnen sie
y15 = 1.0E+15 + 1
und danach die Differenzen
y16 = 1.0E+16 + 1
y15 - 1.0E+15 = 1
Das Beispiel zeigt, dass die relative Änderung einer beliebigen Zahl um
1E-16 ihres Wertes (= nach der 15. Dezimalstelle) nicht mehr darstellbar ist.y16 - 1.0E+16 = 0 Die erreichte Genauigkeit ist das wichtigste praktische Kriterium für den Abbruch einer Reihen-Entwicklung: Man berechnet die Differenz zwischen dem Ergebnis r einer Schleife und dem Ergebnis rv der vorhergehenden Schleife: dr = r - rv
Das Ergebnis ist damit ca. auf ln(dr)/ln(10)
Dezimalstellen genau.● Der binäre Exponent bestimmt die minimale und maximale Größe von Gleitkomma-Zahlen. Mit 11 Bit sind ganze Zahlen bis d=2^11=2048 darstellbar, oder von -1024 bis +1023 Mit diesen binären Exponenten und der maximalen Mantisse ergibt sich
z(min) = 2^-1024 = 1.7977E-308
z(max) = 2^1024 = 1.7977E+308 |
Hexadezimal (16er)-SystemZur anschaulichen Darstellung von binären Daten verwendet man oft das Hex-System mit den 16 Ziffern 0...9,A...FZur Darstellung von je 4 Bit verwendet man genau 1 Hex-Ziffer, da 2^4=16 Für jedes darzustellende Byte braucht man genau 2 Hex-Ziffern, daher ist jedes Byte mit den Zahlen 0x00 bis 0xFF (anders dargestellt #00...#FF) darstellbar. |
Anzahl der mit h Hex-Ziffern darstellbaren positiven ganzen Zahlen: d = 16^h
Anzahl der zur Darstellung einer ganzen Dezimalzahl d
benötigten Hex-Ziffern:
h = ln(d) / ln(16)
Auch in diesem Fall muss man das Ergebnis h auf ganze Hex-Ziffern aufrunden.
|
Anwendung der Logarithmus-Funktion |
|
|
Eine klassische Anwendung des Logarithmus ist die Vereinfachung schwieriger
Rechnungen. Dabei werden immer die beiden Funktionen ln()
und exp()
kombiniert, die einander umkehren. Die Wirkung wird oft so formuliert, dass mit dem Logarithmus die 'Rechnungs-Stufe' herabgesetzt wird: Aus einer Multiplikation wird eine Addition, aus einer Division eine Subtraktion, usw. |
In der Informatik spielen diese Methoden auf Prozessor-Ebene eine
wichtige Rolle: Dort gibt es keine mathematischen Funktionen, in sehr einfachen Prozessoren nicht einmal Multiplikation oder Division. Mit Hilfe der Logarithmus-Funktion kann man auch Rechnungen einer 'höheren' Stufe ausführen. Sowohl die Logarithmus-Funktion als auch die → Exponential-Funktion lässt sich durch ↓ Reihen-Entwicklung berechnen. |
Multiplikation x*yDie Multiplikation wird auf eine Addition der Logarithmen zurückgeführt.ln (x * y) = ln(x) + ln(y) Man berechnet die Logarithmen der Argumente x und y, addiert diese und bestimmt das Exponential der Summe: x * y = exp(ln(x) + ln(y))
Das erscheint heute als Umweg, war jedoch lange Zeit hindurch die Grundlage vieler praktischer und zeitsparender Methoden und Geräte, z.B. des Rechenschiebers. Wenn einmal für längere Zeit der Strom ausfallen sollte, wird man sich daran erinnern... |
Beispiel:
123 * 456 = exp(4.812 + 6.122) = exp(10.935) = 56088
● Diese Methode wird verwendet, um den Algorithmus zur Berechnung des Logarithmus sehr kleiner Argumente x zu beschleunigen: ln(x * 2) = ln(x) + ln(2)
Eine beliebige kleine Zahl x<0.5 wird so oft verdoppelt,
bis 0.5<=x<1 ist. Das kostet zwar Rechenzeit,
spart jedoch meistens wesentlich mehr durch die raschere Ausführung des
↓ Reihen-Algorithmus.
|
Division x/yFunktioniert ähnlich wie die Multiplikation. Sie wird auf eine Subtraktion der Logarithmen zurückgeführt:
ln(x / y) = ln(x) - ln(y)
x / y = exp(ln(x) - ln(y)) Beispiel zur Halbierung einer beliebigen Zahl x
ln(x / 2) = ln(x) - ln(2)
x / 2 = exp(ln(x) - ln(2)) = exp(ln(x) - 0.693) |
● Diese Methode wird verwendet, um Argumente 1>x in den Bereich 0<=x<1 zu transformieren: ln(1 / x) = ln(1) - ln(x) = -ln(x)
weil ln(1)=0 ist. Die Umwandlung ist notwendig, weil der
↓ Reihen-Algorithmus nur
Argumente 0<=x<1 berechnen kann.
|
Potenzierung x^yDie Potenzierung wird auf eine Multiplikation zurückgeführt:
ln(x^y) = ln(x) * y
x ^ y = exp(ln(x) * y) Beispiel:
2 ^ 10 = exp(0.693 * 10) exp(6.931) = 1024
|
• Die Potenzierung mit kleinen ganzzahligen Exponenten y berechnet man meist schneller in einer Schleife: x^3 = x * x * x
für Gleitkomma-Exponenten ist die Verwendung des Logarithmus jedoch die
Standard-Methode.
|
Wurzeln x^(1/x)Das Wurzelziehen wird auf eine Division zurückgeführt:
ln(x^(1/y)) = ln(x) / y
Für die Quadratwurzel wird
x ^ (1/y) = exp(ln(x) / y) sqr(x) = x ^ (1/2) = exp(ln(x) / 2)
Beispiel: 3. Wurzel aus 100 100^(1/3) = exp(4.605 / 3) = exp(1.535) = 4.642
|
• Zur Berechnung einfacher ganzzahliger Wurzeln (Quadratwurzel, Kubikwurzel, ...) verwendet man besser die darauf spezialisierten → Reihen-Algorithmen. Gleitkomma-Wurzeln werden nur selten gebraucht, in diesem Falle verwendet man die Division des Logarithmus als Standard-Methode. |
GenauigkeitWenn man Logarithmen verwendet, um die 'Rechnungs-Stufe' herabzusetzen, dann kann sich dabei die Genauigkeit verringern. Es hängt von der jeweiligen Rechnung (Formel, Algorithmus) ab, wie stark sich ein Fehler von +/-1 der letzten Stelle auf das Ergebnis auswirkt. |
Test: Wenn sie in einer Rechnung y=ln(x) verwenden, dann rechnen sie probeweise auch mit yerr=y*(1+1/1E15) Die Differenz der beiden Ergebnisse ergibt die ungefähre Genauigkeit (numerische Auflösung) ihrer Rechnung. |
|
Beispiel
Die hier vorgestellte Methode wird u.a. auf dieser Seite zur Beschleunigung
eines Algorithmus (Berechnung des
↓ natürlichen Logarithmus) verwendet. Dabei wird eine
(mehrfache) Multiplikation auf die (mehrfache) Addition eines Logarithmus
zurückgeführt.• Eine Zahl x>1 wird durch fortgesetzte Halbierung in einen optimalen Werte-Bereich gebracht, hier z.B. durch 4malige Division durch 2 (das lässt sich binär besonders rasch ausführen):
x = 12
a = x = 12 a = a/2 = 6 a = a/2 = 3 a = a/2 = 1.5 a = a/2 = 0.75 |
• Nun kann man den natürlichen Logarithmus durch ↓ Reihen-Entwicklung einfach und rasch berechnen: b = ln(a) = -0.288
• Um den Logarithmus der Zahl x zu erhalten, wird 4mal der Logarithmus des vorher (links) verwendeten Divisors 2 addiert:
ln(2) = 0.693
b = b + ln(2) = 0.405 b = b + ln(2) = 1.099 b = b + ln(2) = 1.792 b = b + ln(2) = 2.485 • Damit hat man das Ergebnis berechnet - scheinbar auf Umwegen, tatsächlich jedoch besonders schnell: ln(x) = b = 2.485
|
Logarithmische SkalenManchmal ist es notwendig, Zahlenwerte eines besonders großen Werte-Bereichs darzustellen. Dazu verwendet man am besten eine logarithmische Skala.Eine logarithmische Skala zeigt sowohl sehr kleine als auch sehr große Zahlenwerte gleichzeitig an. Allerdings sind nicht alle Menschen in der Lage, eine logarithmische Skala sinnvoll zu interpretieren. Pisa- und andere Tests legen das nahe. |
Quelle:
Wikipedia
1
Aureus = 8.19g Gold (Au)
Wenn Mercatorius das Geld nicht abhebt, sondern seinen Nachkommen vererbt, dann hätte die Bank zunächst keine Probleme, das angesparte Kapital in Gold aufzubringen: Nach 100 Jahren hätte der Wert lediglich 157g betragen, nach 163 Jahren immerhin schon 1kg und nach 396 Jahren 1 Tonne Gold. |
|
Das angesparte Kapital in Gold, als 'gewöhnliches' (=lineares) Diagramm. Der Wert nach 1000 Jahren beträgt 5.63E+13 g. Die vertikale Skala zeigt das angesparte Kapital in Mt (Megatonnen = Mio t) Gold. Im linearen Maßstab kann man nur die großen Zahlenwerte erkennen. Die kleinen Zahlenwerte der ersten 600 Jahre sind in diesem Maßstab nicht erkennbar (Rechtsklick in das Diagramm | Quelltext zeigt die Daten an). |
Dieses Diagramm zeigt die gleichen Daten an, die vertikale Achse ist jedoch im logarithmischen Maßstab angelegt. Man kann nun alle Daten gut erkennen, auch die kleinen Zahlenwerte. Die großen Zahlenwerte werden allerdings weniger genau angezeigt. |
|
Wenn das römische Reich nicht rechtzeitig untergegangen wäre,
dann hätte die Bank allerdings zunehmende Probleme mit den Urenkeln
von Mercatorius bekommen: Im Jahre 630 wären bereits 1000t Gold zu beschaffen, im Jahr 864 1 Mio t Gold. Wenn die Bank alles Gold der Erdkruste bis in eine Tiefe von 4km fördern ließe, dann hätte das theoretisch bis 1661 gereicht. Im Jahre 1944 wäre die Masse des Mondes in Gold fällig gewesen, im Jahre 2093 die Masse der gesamten Erde. |
Wie man sieht, kann ein derartiges System nur für begrenzte Zeiten funktionieren. Langfristig muss es (wie bei jedem Pyramidenspiel) zu einem Kollaps kommen, weil es keine beliebig großen Werte gibt. Das System lässt sich länger erstrecken, wenn die laufende Entwertung größer als der durchschnittliche Zins-Ertrag ist. Irgendwann reicht das nicht mehr aus, und dann werden im Rahmen einer 'Wirtschaftskrise' größere Werte pauschal vernichtet. Nur die SchülerInnen der Grundschule glauben noch daran, dass sich ihr Taschengeld auf einem Sparbuch auf wunderbare Weise vermehren kann. |
Logarithmus-Funktion in Programmen & Programmiersprachen |
|
Natürlicher Logarithmus• Tabellen-Kalkulation (LibreOffice_Calc, OpenOffice-Calc, MS-Excel, ...):=LN(A1)
• C/C++: Bibliothek #include <math.h>
Funktion
double log(double x);
C++ bietet zusätzlich überladene Varianten für die
Typen float, long double, complex, ... Diese Preprocessor-Makros sind meist definiert, werden jedoch als 'system-spezifisch' angegeben:
M_LOG2E = 1.4426950408889634074
M_LOG10E = 0.43429448190325182765 M_LN2 = 0.69314718055994530942 M_LN10 = 2.30258509299404568402 • Javascript Konstanten:
Math.LN2 = 0.693147180559945
Funktion:
Math.LN10 = 2.30258509299405 y=Math.log(x);
|
• Perl Funktion: y=log(x);
• PHP Konstanten:
M_LN2 = 0.69314718055994530942
Funktionen:
M_LN10 = 2.30258509299404568402
y=log(x);
log1p() berechnet ln(1+x)
auch für sehr kleine x rasch und genau.yp=log1p(x)=log(x+1); • Basic (LibreOffice-Basic, VBA): y=Log(x)
• XSL kennt leider keine Logarithmus-Funktion. Man kann mit Reihen-Entwicklung eine eigene Funktion programmieren, um z.B. Diagramme mit logarithmischen Skalen zu erzeugen. |
Dekadischer Logarithmus• Kalkulation (LibreOffice_Calc, OpenOffice-Calc, MS-Excel, ...):=LOG(A1)
Der dekadische Logarithmus wird heute kaum mehr verwendet. Nur wenige Programmiersprachen bieten dafür eigene Funktionen: • C/C++: Bibliothek #include <math.h>
Funktion
double log10(double x);
C++ bietet zusätzlich überladene Varianten für die
Typen float, long double, complex, ...
|
• PHP Funktion: y=log10(x);
• Basic (LibreOffice-Basic, VBA) : y=Log10(x)
In jedem anderen Fall berechnet manlog10(x)=ln(x) / ln(10) mit Hilfe des natürlichen Logarithmus. |
LibreOffice
-
Kosten- und lizenzfreie Office-Programme (inkl. Kalkulation) für alle
gängigen Betriebssysteme und Sprachen, kompatibel mit MS-Excel. Java -
Programmiersprache von Sun / Oracle, kostenfrei für alle gängigen Systeme.
Home● Javascript - Programmiersprache, in jedem gängigen Browser-Programm integriert. Perl -
Programmiersprache, in jeder Linux_Distribution kostenfrei enthalten, für
Windows kostenfrei bei
ActiveState PHP -
Programmiersprache, kosten- und lizenzfrei für alle gängigen Systeme.
Home: php.net● Basic (VBA) - Programmierrsprache von Microsoft oder als OpenSource-Version, in jedem gängigen Kalkulations-Programm (OpenOffice, LibreOffice, Excel) integriert. |
Wikipedia: Logarithmus,
Exponential,
Euler'sche Zahl,
Taylor-Reihe,
Reihe,
Potenzreihe, Formelsammlung: Reihenentwicklungen |
Logarithmus-Funktion als Potenzreihe |
||||||||||||||||||||||||||||||||||||||||||||||||||||
Zur Berechnung des natürlichen Logarithmus verwendet man diese Reihe:
![]()
Quelle:
Wikipedia
|
● Dieser Algorithmus gilt nur für 0<x<1 ● Für x<0 ist die Logarithmus-Funktion selbst nicht definiert. ● Der Wert ln(1)=0 wird nicht berechnet, sondern direkt angegeben. ● Argumente 1>x muss man zuerst in den Bereich des Algorithmus transformieren, danach werden sie berechnet, so wie angegeben. |
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
Zur numerischen Berechnung kann man den Algorithmus jedoch wesentlich
einfacher formulieren:
b = (1-x)
ln (x) = - [b + b^2/2 + b^3/3 + b^4/4 + ...] |
Diese Form erspart die Berechnung des alternierenden Vorzeichens und verwendet nur die Addition (= die schnellste der 4 Grundrechnungs-Arten). | |||||||||||||||||||||||||||||||||||||||||||||||||||
Algorithmus:• Man braucht einen Zähler, hier mit n bezeichnet:n = 1, 2, 3, 4, ...
• Mit jedem Zähler-Wert berechnet man ein Element der Reihe element[n] = b^n/b
• Der Anfangswert einer Summen-Variablen wird mit sum=0 festgelegt. Unmittelbar nach seiner Berechnung wird jedes Element zur 'laufenden Summe' addiert:
sum = 0
sum = sum + element[1] sum = sum + element[2] sum = sum + element[3]... |
• Die Reihe wird (in der Standard-Version) so lange fortgesetzt, bis sich sie laufende Summe sum nach Addition eines sehr kleinen element's nicht mehr ändert. • Das Ergebnis ist ln(x) = -sum
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Der Algorithmus ist stark vom Zahlenwert des
Arguments 0<x<1 abhängig:
Das Ziel wird für große x (nahe 1) rasch erreicht,
für kleine x (nahe 0) dagegen sehr langsam. Das Diagramm zeigt, wie viele Iterations-Schritte (Y-Achse) man ungefähr braucht, um eine gewünschte Genauigkeit zu erreichen. Die Genauigkeit des Ergebnisses wird hier für 5 Dezimal-Stellen (● blau), 10 Stellen (● violett) und 15 Stellen (● rot) angezeigt. Die Genauigkeit von Standard (Double Precision) Gleitkomma-Zahlen beträgt 15-16 Dezimalstellen. Die rote Kurve markiert daher die Grenze für Kalkulations-Programme und Programmiersprachen (ohne besondere Variablen-Typen). Die Daten wurden empirisch gewonnen und geglättet. Sie sind lediglich Richtwerte ! Beispiel: Für ein Argument x=0.6 braucht man ca. 10 Schritte, um den Logarithmus auf 5 Ziffern genau zu berechnen, 24 Schritte für 10 Ziffern oder 38 Schritte für 15 Ziffern. Im Kapitel ↓ Optimierung wird gezeigt, wie man dieses Verhalten ausnützen kann, um rascher zu rechnen: Man transformiert alle 0<x<0.5 in den Bereich 0.5<x<1 wo man den Logarithmus mit wesentlich weniger Schritten berechnen kann. |
Anzahl der Iteratios-Schritte als Funktion des Arguments bei der iterativen Berechnung der Funktion y = ln(x) |
|||||||||||||||||||||||||||||||||||||||||||||||||||
Anpassung des Algorithmus |
|
| Der oben angegebene Reihen-Algorithmus gilt nur für Argumente im Bereich 0>x<1 |
Für alle anderen Argumente x>1 nutzt
man diese Eigenschaft der Logarithmus-Funktion:
ln(x) = -ln(1/x)
und bringt damit beliebige Argumente x>1
in den berechenbaren Bereich.
|
Hilfs-VariableAlle hier vorgestellten Beispiele verwenden die beidenHilfs-Variablen a und v ► Vor Beginn des einfachen Reihen-Algorithmus wird das Argument in den berechenbaren Bereich transformiert:
Für x<1: a = x; v = 1;
Für x>1: a = 1/x v = -1; Mit a wird der Logarithmus berechnet, in der Variablen v merkt man sich, ob das Argument x transformiert wurde oder nicht. |
► Der Reihen-Algorithmus wird so berechnet wie ↑ oben vorgestellt:
b = (1-x)
sum = [b + b^2/2 + b^3/3 + b^4/4 + ...] ► Nach dem Abbruch der Schleife wird das Vorzeichen des Ergebnisses je nach der Vorgeschichte umgekehrt: |
Optimierung des Algorithmus |
|
|
Ansatzpunkt ist das bei Vorstellung des
↑ einfachen Reihen-Algorithmus gezeigte Diagramm: • Jeder Schleifen-Durchgang kostet ungefähr die gleiche Rechenzeit. Man kann durch Verringerung der Schleifen-Anzahl viel Zeit sparen. • Andererseits kostet es Zeit, um mit zusätzlichen Maßnahmen das Argument vor Beginn des Schleifen-Algo in den optimalen Bereich nahe an x<1 zu bringen. |
Faustregel: • Bei geringer Anforderung an die Genauigkeit (Mess- und Regeltechnik, Mikroprozessoren) ist eine Optimierung - wenn überhaupt - nur bei sehr kleinen x<0.1 sinnvoll. • Bei Standard-Genauigkeit (15 Dezimalstellen) ist eine Optimierung bei x<0.5 meist sinnvoll. • Es hängt vom durchschnittlichen Werte-Bereich der Argumente x ab, ob und welche Optimierung sich lohnt. Sie sollten Live-Tests ausführen, wenn die Rechenzeit kritisch ist. |
Optimierung:Der Algorithmus rechnet für Argumente 0.5...x...1 angenehm rasch. Leider wächst die Anzahl der Iterationen und die Rechenzeit mit wesentlich kleineren oder größeren Argumenten sehr rasch.Man kann sich mit fortgesetzter Halbierung großer Argumente x helfen:
ln(x) = ln(x/2) + 1 * ln(2)
usw. bis x<1 ln(x) = ln(x/4) + 2 * ln(2) ln(x) = ln(x/8) + 3 * ln(2) Für sehr kleine Argumente gilt umgekehrt: ln(x) = ln(2*x) - ln(2)
|
Lösung:
Man zählt, wie oft man das Argument x halbieren
(oder verdoppeln) muss, um 0.5...x...<1 zu erhalten.
Danach wird (rasch) ln(x) berechnet
und ln(2) genauso oft addiert (subtrahiert), wie man
vorher halbieren (verdoppeln) musste.Ein weiterer Vorteil ist, dass die Halbierung oder Verdoppelung im intern verwendeten → Binärsystem besonders rasch funktioniert. |
Logarithmus-Funktion mit Basic (LibreOffice-Basic, Visual Basic VBA) |
|
Programmierung mit Basic (LibreOffice-Basic, Visual Basic VBA)Argumente:
Die Funktion my_ln() akzeptiert 2 Argumente:x ... Zahl, deren natürlicher Logarithmus 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. Hilfs-Variable: a,b ... so wie oben beschrieben Vorbereitung: In 2 While-Schleifen wird a so lange verdoppelt oder halbiert, bis 0.5<=a<1 ist. Die Variable h zählt die Anzahl der Verdoppelungen bzw. Halbierungen. Anfangswerte:
doloop ... Schalter, steuert entweder die weitere
Berechnung oder den Abbruchve ... Vorzeichen des jeweiligen Elements sum ... Ergebnis der Reihen-Entwicklung (laufende Summe der berechneten Elemente) n ... Zähler für die Elemente (Schritte) Schleife
In jedem Schleifen-Durchlauf wird 1 Element berechnet.element ... Das in der jeweiligen Schleife berechnete Element der Reihe Abbruch:
Das jeweils vorige Ergebnis sumv wird mit dem aktuellen
Ergebnis sum verglichen: Wenn keine Änderung erfolgt
ist, oder wenn der Zähler seinen Maximalwert erreicht hat, dann
wird doloop=False gesetzt und damit die
Schleife abgebrochen.Abschluss
Nach Abbruch der Schleife wird die Summe sum mit dem
Vorzeichen v multipliziert und als Ergebnis zurückgegeben.Vereinfachung:
Die Sonderfälle x<=0 (ergibt Fehler)
und x=1 (ergibt die ↓ Euler-Zahl) werden im
Beispiel nicht berücksichtigt.Hilfs-Funktion:
Eine Reihen-Entwicklung ist dann sinnvoll, wenn man dafür keine anderen
Funktionen benötigt. Daher wird an Stelle des Potenz-Operators
(b^n) die
↓ Hilfs-Funktion my_pow() verwendet:
Damit ist der gesamte Algorithmus mit den 4 Grundrechnungs-Arten
durchführbar.♣ Vereinfachung: Der Sonderfall x=1 wird in dieser Version nicht berücksichtigt. |
Reihen-Entwicklung der Logarithmus-Funktion als Basic-(VBA)-Funktion (vereinfacht):
Const LN2 = 0.693147180559945
Function my_ln( _
x As Double, _
Dim doloop As BooleanOptional nmax As Integer = -1) _ As Double Dim h, ve, n As Integer Dim a, b, element, sum, sumv As Double
If nmax < 0 Then nmax = 1000
End Function
' If IsMissing(nmax) Then nmax = 1000
' Vorbereitung
h = 0a = x While a < 0.5
a = a * 2
Wendh = h - 1 While a > 1
a = a / 2
Wend
h = h + 1 ' Anfangswerte
b = a - 1n = 1 ve = 1 sum = 0 doloop = True ' Berechnungs-Schleife
While (doloop)
sumv = sum
Wend' element = ve * b ^ n / n
element = ve * my_pow(b, n) / nsum = sum + element n = n + 1 If (sum=sumv Or n>=nmax) Then doloop = False ve = ve * -1 my_ln = sum + h * LN2 Private Function my_pow( _
ByVal number As Double, _
Dim i As IntegerByVal exponent As Integer) _ As Double Dim p As Double
p = 1
End Function
For i = 1 To exponent p = p * number
Nextmy_pow = p |
|
Anwendung
Man kann das Basic-Programm als 'Benutzerdefinierte Funktion' in jedem Kalkulations-Programm
verwenden. Zur Berechnung bis an die Grenze der Genauigkeit geben sie z.B. diese Formel ein:
E2=my_ln(B1)
(Annahme: Das Argument x befindet sich in
Zelle B1 )
|
Zur Berechnung einer begrenzten Anzahl von Elementen geben sie z.B. diese Formel ein: E7=my_ln($B$1;A7)
Diese Formel kann man nach unten ausfüllen. Das Ergebnis sollte gleich oder sehr
ähnlich jenem des Kalkulations-Programms in Spalte D sein.
|
Logarithmus-Funktion mit Javascript |
|
Programmierung mit JavascriptDie Funktion ist im Quelltext dieser Webseite enthalten und rechnet Live, wenn sie den Button klicken:
Live-Ergebnis:
Argument x = ?
my_ln(x) = ? ln_theor(x) = ? Genauigkeit ≈ ? Dezimalstellen Anzahl der Iterationen = ? Rechenzeit = ? µs ● Der Sonderfall x=1 wird nicht mit Reihen-Entwicklung berechnet, sondern direkt das Ergebnis ln(1)=0 zurückgegeben. |
Reihen-Entwicklung der Logarithmus-Funktion als
Javascript-(JS)-Funktion.
function my_ln(x,nmax) {
if(x==1) {return 0;}
}
else{
if(nmax<0) {nmax=1000;}
}
var a=x; var h=0; while(a<0.5) {a*=2; h--;} while(a>1) {a/=2; h++;} var b = a - 1; var sum=0; var sumv=0; var ve=1; var element=0; var n = 1; var doloop = true; while(doloop) {
sumv = sum;
}element = ve * my_pow(b,n) / n; sum += element; n++; if(sum==sumv || n>=nmax) {doloop=false;} ve *= -1; return sum + h * Math.LN2; |
Hilfs-Funktionen |
|
| Die meisten Programmiersprachen bieten mindestens einige grundlegende mathematische Funktionen. Sie sind entweder in der Grundausrüstung enthalten oder werden als Modul (Bibliothek...) bei Bedarf eingebunden. | Wenn jedoch die benötigten Funktionen fehlen, oder - wie bei einfachen MikroProzessoren - überhaupt keine mathematischen Funktionen verfügbar sind, dann muss man eigene Funktionen programmieren, welche ausschließlich die 4 Grundrechnungs-Arten (Addition, Subtraktion, Multiplikation, Division) verwenden. |
Potenz-FunktionDiese Funktion ist je nach Programmiersprache als Funktion (meist unter Namen wie pow() ) oder Operator (oft als ^ oder ** ) verfügbar.♣ Bei Verwendung großer Zahlenwerte (= langer Iterations-Reihen) kann man an die Grenze des Variablen-Typs kommen, das ist für den Typ Double ca 1.8E+308 Das Beispiel zeigt, wie man die Potenz-Funktion selbst programmieren kann. Anwendung: x_hoch_y = my_pow(x,y)
|
Basic (VBA)
Hilfs-Funktion my_pow()
Private Function my_pow( _
ByVal number As Double, _
Dim i As IntegerByVal exponent As Integer) _ As Double Dim p As Double
p = 1
End Function
For i = 1 To exponent p = p * number
Nextmy_pow = p |
|
Javascript
Hilfs-Funktion my_pow()
function my_pow(b,ie) {
Anwendung in Javascript:
var p=1;
}
for(var i=1;i<=ie;i++) {p*=b;} return p; x_hoch_y = my_pow(x,y);
|
C/C++
Hilfs-Funktion my_pow() Deklaration: double my_pow(double,int);
Funktion:
double my_pow(double b,int ie) {
Anwendung in C/C++:
int i;
}
double p=1; for(i=0;i<ie;i++) {p*=b;} return p; x_hoch_y = my_pow(x,y);
|
Fakultät-FunktionDas Beispiel zeigt, wie man die → Fakultät-Funktion (engl. factorial) ausschließlich unter Verwendung der 4 Grundrechnungs-Arten programmieren kann:x_fakt = 1 * 2 * 3 * ... * x
♣ Die Fakultät-Funktion wächst besonders rasch: Sie ist nur verwendbar bis maximal 170! = 7.26E+306
|
Basic (VBA)
Hilfs-Funktion my_fakt()
Private Function my_fakt( _
ByVal number As Integer) _
Dim i As IntegerAs Double Dim f As Double
f = 1
End Function
For i = 1 To number f = f * i
Nextmy_fakt = f Anwendung: x_fakultaet = my_fakt(x)
|
|
Javascript
Hilfs-Funktion my_fakt()
function my_fakt(n) {
Anwendung in Javascript:
var f=1;
}
for(var i=1;i<=n;i++) {f*=i;} return f; n_fakultaet = my_fakt(n);
|
C / C++
Hilfs-Funktion my_fakt() Deklaration: double my_fakt(int);
Funktion:
double my_fakt(int n) {
Anwendung in C / C++:
int i;
}
double f=1; for(i=1;i<=n;i++) {f*=(double)i;} return f; n_fakultaet = my_fakt(n);
|
Quadratwurzel-FunktionDiese Funktion wird von den meisten Programmiersprachen als sqr() oder sqrt() angeboten. |
Die Berechnung mit Hilfe einer Reihen-Entwicklung wird auf der Seite → Quadratwurzel demonstriert. |