Was verursacht Gleitkomma-Rundungsfehler?

62

Mir ist bewusst, dass Gleitkomma-Arithmetik Präzisionsprobleme hat. Normalerweise überwinde ich sie, indem ich zu einer festen Dezimaldarstellung der Zahl wechsle oder einfach den Fehler vernachlässige.

Ich weiß jedoch nicht, was die Ursachen für diese Ungenauigkeit sind. Warum gibt es so viele Rundungsprobleme mit Gleitkommazahlen?

nmat
quelle
28
Um genau zu sein, es ist nicht wirklich der Fehler , der durch Rundungen verursacht wird, über den sich die meisten Menschen Sorgen machen - es ist die Tatsache, dass sich die binäre Gleitkommarundung auf unintuitive Weise verhält. Das Umschalten auf eine Dezimaldarstellung kann das Rundungsverhalten intuitiver gestalten, im Gegenzug erhöhen Sie jedoch fast immer den relativen Fehler (oder müssen den Speicherplatz erhöhen, um dies zu kompensieren).
Daniel Pryden
12
Mein Versuch, die häufigsten Verwirrungen
Michael Borgwardt
Ich denke, @DanielPryden bedeutet: " Wenn Sie zu einer [Festkomma-] Darstellung wechseln, kann sich die Rundung intuitiver verhalten ..." . was bewirkt , dass Probleme Abrunden, ob sie befestigt ist oder Gleitkommazahlen ist die endliche Wortbreite von entweder. es ist nur so, dass bei Gleitkommazahlen die Größe des Rundungsfehlers normalerweise in etwa proportional zur Größe der gerundeten Zahl bleibt. (es sei denn, Sie werden sehr klein und "denormalisiert" Zahlen.)
Robert Bristow-Johnson
@robert: Das ist nicht genau das, worauf ich mich bezog. Der "Fehler", dem die meisten Menschen mit Fließkomma begegnen, hat nichts mit Fließkomma an sich zu tun, sondern ist die Basis. IEEE-754-Gleitkommazahlen und -Doppelkommazahlen verwenden einen Exponenten in Basis 2, was bedeutet, dass gebrochene Zahlen auf negative Zweierpotenzen (1/2, 1/16, 1/1024 usw.) und nicht auf negative Zehnerpotenzen (1 / 10, 1/1000 usw.) Dies führt zu nicht intuitiven Ergebnissen wie 0,1 auf 0,1000001 und ähnlichen Problemen.
Daniel Pryden
Sie können Fließkommazahlen in der Basis 10 eingeben - so funktioniert der .NET- decimalTyp. Ein fester Punkt ist dagegen anders. Solange Ihre Reichweite begrenzt ist, ist der Fixpunkt eine gute Antwort. Aufgrund des eingeschränkten Bereichs ist Festkomma jedoch für viele mathematische Anwendungen ungeeignet, und die Implementierung von Festkommazahlen ist in der Hardware häufig nicht gut optimiert.
Daniel Pryden

Antworten:

82

Dies liegt daran, dass einige Brüche eine sehr große (oder sogar unendliche) Anzahl von Stellen benötigen, um ohne Rundung ausgedrückt zu werden. Dies gilt sowohl für die Dezimalnotation als auch für die Binärnotation. Wenn Sie die Anzahl der für Ihre Berechnungen zu verwendenden Dezimalstellen begrenzen würden (und keine Berechnungen in Bruchnotation durchführen würden), müssten Sie sogar einen einfachen Ausdruck mit 1/3 + 1/3 runden. Statt 2/3 zu schreiben, müssten Sie 0,33333 + 0,33333 = 0,66666 schreiben, was nicht mit 2/3 identisch ist.

Im Falle eines Computers ist die Anzahl der Stellen durch die technische Natur seiner Speicher- und CPU-Register begrenzt. Die intern verwendete Binärnotation fügt einige weitere Schwierigkeiten hinzu. Computer können Zahlen normalerweise nicht in Bruchnotation ausdrücken, obwohl einige Programmiersprachen diese Fähigkeit hinzufügen, wodurch diese Probleme bis zu einem gewissen Grad vermieden werden können.

Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte

thorsten müller
quelle
12
Spot on. Aber ich würde auch bemerken, dass einige Zahlen, die mit Dezimalzahlen enden, nicht mit Binärzahlen enden. Insbesondere 0.1 ist eine wiederkehrende Zahl in binärer Form und daher kann keine Gleitkommazahl genau 0.1 darstellen.
Jack Aidley
4
Fließkommazahlen sind nicht nur für viele Dezimalstellen nützlich. 32-Bit-Ganzzahlen können nur bis zu 4 Milliarden zählen, ein 32-Bit-Float kann jedoch nahezu unendlich groß sein.
Abhi Beckert
7
Insbesondere sind die Brüche, die wir als endliche Dezimalstellen ausdrücken können, diejenigen, deren Primfaktor-Faktorisierung nur 2 und 5 enthält (z. B. können wir 3/10 und 7/25 ausdrücken, aber nicht 11/18). Wenn wir zu binär wechseln, verlieren wir den Faktor 5, so dass nur die dyadischen Rationen (z. B. 1/4, 3/128) exakt ausgedrückt werden können.
David Zhang
70

Rundungsfehler entstehen in erster Linie dadurch, dass die Unendlichkeit aller reellen Zahlen unmöglich durch den endlichen Speicher eines Computers dargestellt werden kann , geschweige denn durch eine winzige Speicherscheibe wie eine einzelne Gleitkommavariable , von der viele gespeicherte Zahlen nur Näherungswerte sind die Zahl, die sie darstellen sollen.

Da es nur eine begrenzte Anzahl von Werten gibt, die keine Näherung darstellen, und jede Operation zwischen einer Näherung und einer anderen Zahl zu einer Näherung führt, sind Rundungsfehler fast unvermeidlich .

Es ist wichtig zu erkennen, wann sie wahrscheinlich ein Problem verursachen, und Maßnahmen zu ergreifen, um die Risiken zu mindern .


Zusätzlich zu David Goldbergs grundlegendem Wissen, das jeder Informatiker über Fließkomma-Arithmetik wissen sollte (von Sun / Oracle als Anhang zu ihrem Numerical Computation Guide neu veröffentlicht ), das von Thorsten erwähnt wurde, lieferte das ACCU- Journal Overload eine hervorragende Leistung Artikelserie von Richard Harris über den Floating Point Blues .

Die Serie begann mit

Numerisches Rechnen hat viele Fallstricke. Richard Harris beginnt nach einer Silberkugel zu suchen.

Der Drache des numerischen Fehlers wird nicht oft aus seinem Schlummer geweckt, aber wenn er sich unachtsam nähert, fügt er den Berechnungen des unachtsamen Programmierers gelegentlich katastrophalen Schaden zu.

So sehr, dass einige Programmierer, die ihn in den Wäldern der Gleitkomma-Arithmetik nach IEEE 754 entdeckt haben, ihren Kollegen davon abraten, in dieses schöne Land zu reisen.

In dieser Artikelserie werden wir die Welt des numerischen Rechnens erforschen und die Gleitkomma-Arithmetik mit einigen der Techniken vergleichen, die als sicherer Ersatz dafür vorgeschlagen wurden. Wir werden erfahren, dass das Territorium des Drachen tatsächlich weitreichend ist und dass wir im Allgemeinen vorsichtig vorgehen müssen, wenn wir seine verheerende Aufmerksamkeit fürchten.

Richard erklärt zunächst die Taxonomie von reellen Zahlen, rational, irrational, algebraisch und transzendental. Anschließend erklärt er die IEEE754-Darstellung, bevor er auf Abbruchfehler und Ausführungsreihenfolgeprobleme eingeht.

Wenn Sie nicht tiefer lesen, haben Sie eine hervorragende Grundlage für die Probleme, die mit Gleitkommazahlen verbunden sind.

Wenn Sie jedoch mehr wissen möchten, fährt er fort

Anschließend versucht er, Ihnen bei der Heilung Ihres Calculus Blues zu helfen

und last but not least gibt es

Die gesamte Artikelserie ist einen Blick wert und mit insgesamt 66 Seiten immer noch kleiner als die 77 Seiten des Goldberg-Papiers .

Obwohl diese Reihe fast denselben Bereich abdeckt, fand ich sie zugänglicher als Goldbergs Artikel . Ich fand es auch einfacher, die komplexeren Teile des Papiers zu verstehen, nachdem ich die früheren Artikel von Richards gelesen hatte. Nach diesen frühen Artikeln verzweigt sich Richard in viele interessante Bereiche, auf die das Goldberg-Papier keinen Einfluss hat.


Wie so spricht ak in den Kommentaren erwähnt:

Als Autor dieser Artikel möchte ich erwähnen, dass ich interaktive Versionen davon auf meinem Blog www.thusspakeak.com erstellt habe, beginnend mit thusspakeak.com/ak/2013/06 .

Mark Booth
quelle
1
Als Autor dieser Artikel möchte ich erwähnen, dass ich interaktive Versionen davon auf meinem Blog www.thusspakeak.com erstellt habe, beginnend mit thusspakeak.com/ak/2013/06 .
Also sprach ak
Vielen Dank an thusspakea.k. Ich habe meiner Antwort eine Notiz hinzugefügt, und diese interaktiven Elemente funktionieren sehr gut.
Mark Booth
12

Nun, Thorsten hat den endgültigen Link . Ich würde hinzufügen:

Jede Form der Darstellung weist Rundungsfehler für eine bestimmte Zahl auf. Versuchen Sie, 1/3 in IEEE-Gleitkomma oder als Dezimalzahl auszudrücken. Weder kann es genau tun. Dies geht über die Beantwortung Ihrer Frage hinaus, aber ich habe diese Faustregel erfolgreich angewendet:

  • Speichern Sie vom Benutzer eingegebene Werte in Dezimalform (da sie mit ziemlicher Sicherheit in Dezimalform eingegeben wurden - nur sehr wenige Benutzer verwenden Binär- oder Hexadezimalform). Auf diese Weise haben Sie immer die exakte vom Benutzer eingegebene Darstellung.
  • Wenn Sie vom Benutzer eingegebene Brüche speichern müssen, speichern Sie den Zähler und den Nenner (auch in Dezimalzahl).
  • Wenn Sie ein System mit mehreren Maßeinheiten für dieselbe Größe (wie Celsius / Fahrenheit) haben und der Benutzer beide eingeben kann, speichern Sie den eingegebenen Wert und die Einheiten, in denen sie eingegeben wurden. Versuchen Sie nicht, umzurechnen und zu speichern unter eine einzelne Darstellung, es sei denn, Sie können dies ohne Verlust an Genauigkeit tun. Verwenden Sie bei allen Berechnungen den gespeicherten Wert und die Einheiten.
  • Speichern Sie maschinengenerierte Werte im IEEE-Gleitkomma (dies können Zahlen sein, die von einem elektronischen Messgerät wie einem analogen Sensor mit A / D-Wandler oder dem ungerundeten Ergebnis einer Berechnung generiert wurden). Beachten Sie, dass dies nicht gilt, wenn Sie einen Sensor über eine serielle Verbindung lesen und Ihnen den Wert bereits in einem Dezimalformat (z. B. 18,2 C) anzeigen.
  • Speichern Sie vom Benutzer anzeigbare Summen usw. als Dezimalzahl (wie ein Bankkontostand). Richtig runden, aber diesen Wert als endgültigen Wert für alle zukünftigen Berechnungen verwenden.
Scott Whitlock
quelle
Ich würde hinzufügen: Erwägen Sie die Verwendung eines mathematischen Pakets mit beliebiger Genauigkeit wie ARPREC oder decNumber.
Blrfl
Ich habe nicht den Vorteil, dass Dezimalzahlen (im Gegensatz zu Binärzahlen) für ganzzahlige Werte wie Zähler und Nenner eines Bruchs von großem Nutzen sind. Entweder können exakte Ganzzahlwerte gespeichert werden, und binär ist effizienter. Das Hin- und Herwandeln von Eingaben und Ausgaben ist mit einigen Kosten verbunden, die jedoch wahrscheinlich durch die Kosten für die physische Ausführung der E / A überfordert sind.
Keith Thompson
10

Was bisher anscheinend nicht erwähnt wurde, sind die Konzepte eines instabilen Algorithmus und eines schlecht konditionierten Problems . Ich werde zuerst auf die ersteren eingehen, da dies eine häufigere Gefahr für unerfahrene Numeriker darstellt.

Betrachten Sie die Berechnung der Potenzen des (reziproken) goldenen Schnitts φ=0.61803…. Eine Möglichkeit ist die Verwendung der Rekursionsformel φ^n=φ^(n-2)-φ^(n-1), beginnend mit φ^0=1und φ^1=φ. Wenn Sie diese Rekursion in Ihrer bevorzugten Computerumgebung ausführen und die Ergebnisse mit genau bewerteten Leistungen vergleichen, werden Sie eine langsame Erosion signifikanter Zahlen feststellen. Folgendes passiert zum Beispiel in Mathematica :

ph = N[1/GoldenRatio];  
Nest[Append[#1, #1[[-2]] - #1[[-1]]] & , {1, ph}, 50] - ph^Range[0, 51]  
{0., 0., 1.1102230246251565*^-16, -5.551115123125783*^-17, 2.220446049250313*^-16, 
-2.3592239273284576*^-16, 4.85722573273506*^-16, -7.147060721024445*^-16, 
1.2073675392798577*^-15, -1.916869440954372*^-15, 3.1259717037102064*^-15, 
-5.0411064211886014*^-15, 8.16837916750579*^-15, -1.3209051907825398*^-14, 
2.1377864756200182*^-14, -3.458669982359108*^-14, 5.596472721011714*^-14, 
-9.055131861349097*^-14, 1.465160458236081*^-13, -2.370673237795176*^-13, 
3.835834102607072*^-13, -6.206507137114341*^-13, 1.004234127360273*^-12, 
-1.6248848342954435*^-12, 2.6291189633497825*^-12, -4.254003796798193*^-12, 
6.883122762265558*^-12, -1.1137126558640235*^-11, 1.8020249321541067*^-11, 
-2.9157375879969544*^-11, 4.717762520172237*^-11, -7.633500108148015*^-11, 
1.23512626283229*^-10, -1.9984762736468268*^-10, 3.233602536479646*^-10, 
-5.232078810126407*^-10, 8.465681346606119*^-10, -1.3697760156732426*^-9, 
2.216344150333856*^-9, -3.5861201660070964*^-9, 5.802464316340953*^-9, 
-9.388584482348049*^-9, 1.5191048798689004*^-8, -2.457963328103705*^-8, 
3.9770682079726053*^-8, -6.43503153607631*^-8, 1.0412099744048916*^-7, 
-1.6847131280125227*^-7, 2.725923102417414*^-7, -4.4106362304299367*^-7, 
7.136559332847351*^-7, -1.1547195563277288*^-6}

Das angebliche Ergebnis für φ^41hat das falsche Vorzeichen, und noch früher haben die berechneten und tatsächlichen Werte für φ^39keine gemeinsamen Ziffern ( 3.484899258054952* ^ - 9 for the computed version against the true value7.071019424062048 *^-9). Der Algorithmus ist daher instabil, und man sollte diese Rekursionsformel nicht in ungenauer Rechnung verwenden. Dies liegt an der inhärenten Natur der Rekursionsformel: Es gibt eine "abklingende" und "wachsende" Lösung für diese Rekursion und der Versuch, die "abklingende" Lösung durch Vorwärtslösung zu berechnen, wenn es eine alternative "wachsende" Lösung gibt für numerische Trauer. Man sollte also sicherstellen, dass seine numerischen Algorithmen stabil sind.

Nun zum Konzept eines schlecht konditionierten Problems: Auch wenn es einen stabilen Weg gibt, etwas numerisch zu tun, kann es durchaus sein, dass das Problem, das Sie gerade haben, von Ihrem Algorithmus nicht gelöst werden kann. Dies liegt am Problem selbst und nicht an der Lösungsmethode. Das kanonische Beispiel in der Numerik ist die Lösung linearer Gleichungen mit der sogenannten "Hilbert-Matrix":

Hilbert-Matrix

Die Matrix ist das kanonische Beispiel für eine schlecht konditionierte Matrix: Wenn Sie versuchen, ein System mit einer großen Hilbert-Matrix zu lösen, erhalten Sie möglicherweise eine ungenaue Lösung.

Hier ist eine Mathematica- Demonstration: Vergleichen Sie die Ergebnisse der exakten Arithmetik

Table[LinearSolve[HilbertMatrix[n], HilbertMatrix[n].ConstantArray[1, n]], {n, 2, 12}]
{{1, 1}, {1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 
  1}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1,
   1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

und ungenaue Arithmetik

Table[LinearSolve[N[HilbertMatrix[n]], N[HilbertMatrix[n].ConstantArray[1, n]]], {n, 2, 12}]
{{1., 1.}, {1., 1., 1.}, {1., 1., 1., 1.}, {1., 1., 1., 1., 1.},  
  {1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1.}, 
  {1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1., 1.},  
  {1., 1., 1., 0.99997, 1.00014, 0.999618, 1.00062, 0.9994, 1.00031, 
  0.999931}, {1., 1., 0.999995, 1.00006, 0.999658, 1.00122, 0.997327, 
  1.00367, 0.996932, 1.00143, 0.999717}, {1., 1., 0.999986, 1.00022, 
  0.998241, 1.00831, 0.975462, 1.0466, 0.94311, 1.04312, 0.981529, 
  1.00342}}

(Wenn Sie es in Mathematica ausprobiert haben , werden Sie einige Fehlermeldungen bemerken, die auf eine schlechte Konditionierung hinweisen.)

In beiden Fällen ist es keine Heilung, einfach die Präzision zu erhöhen. es wird nur die unvermeidliche Erosion von Zahlen verzögern.

Dies ist, was Sie konfrontiert werden könnten. Die Lösungen könnten schwierig sein: Zum einen gehen Sie entweder zurück zum Zeichenbrett oder stöbern in Zeitschriften / Büchern / was auch immer, um herauszufinden, ob jemand anderes eine bessere Lösung gefunden hat als Sie; Zum anderen geben Sie das Problem entweder auf oder formulieren es neu, sodass es leichter zu lösen ist.


Ich werde Sie mit einem Zitat von Dianne O'Leary verlassen:

Das Leben wirft uns vielleicht ein paar schlecht konditionierte Probleme zu, aber es gibt keinen guten Grund, sich mit einem instabilen Algorithmus zufrieden zu geben.


quelle
9

da Dezimalzahlen zur Basis 10 nicht in Basis 2 ausgedrückt werden können

oder mit anderen Worten, 1/10 kann nicht in einen Bruch mit einer Potenz von 2 im Nenner umgewandelt werden (was im Wesentlichen Gleitkommazahlen sind).

Ratschenfreak
quelle
11
Nicht genau richtig: 0,5 und 0,25 können in der Basis 2 ausgedrückt werden. Ich denke, Sie meinen "nicht alle Dezimalzahlen der Basis 10".
Scott Whitlock
3
Genauer. Nicht alle Bruchzahlen können mit einer Gleitkommanotation exakt dargestellt werden (dh mit der. Sowohl Basis 2 als auch Basis 10 haben genau dieses Problem). Versuchen Sie es 9*3.3333333in Dezimalzahlen und vergleichen Sie es mit9*3 1/3
Martin York
1
Dies ist die häufigste Ursache für Gleitkomma-Verwirrung. .1 + .1 != .2da binäre Gleitkommacodierung verwendet wird, nicht dezimal.
Sean McMillan
@ SeanMcMillan: Und 1.0/3.0*3.0 != 1.0da Gleitkomma-Binärcodierung verwendet wird, nicht Trinary.
Keith Thompson
8

In der Mathematik gibt es unendlich viele rationale Zahlen. Eine 32-Bit-Variable kann nur 2 32 verschiedene Werte und eine 64-Bit-Variable nur 2 64 Werte haben. Daher gibt es unendlich viele rationale Zahlen, die keine genaue Darstellung haben.

Wir könnten Schemata entwickeln, mit denen wir 1/3 oder 1/100 perfekt darstellen können. Es stellt sich heraus, dass dies für viele praktische Zwecke nicht sehr nützlich ist. Es gibt eine große Ausnahme: In der Finanzwelt tauchen häufig Dezimalbrüche auf. Das liegt hauptsächlich daran, dass Finanzen im Wesentlichen eine menschliche und keine physische Tätigkeit sind.

Aus diesem Grund verwenden wir normalerweise binäre Gleitkommazahlen und runden jeden Wert, der nicht binär dargestellt werden kann. Im Finanzbereich wählen wir manchmal dezimale Gleitkommazahlen und runden die Werte auf den nächsten Dezimalwert.

MSalters
quelle
2
Schlimmer noch, während eine unendliche (zählbar unendliche) Menge an Gedächtnis es einem ermöglichen würde, alle Rationen darzustellen, würde es nicht ausreichen, um die Realitäten darzustellen. Noch schlimmer ist, dass fast alle reellen Zahlen keine berechenbaren Zahlen sind. Das Beste, was wir mit einer endlichen Menge an Speicher tun können, ist die Annäherung an eine endliche Teilmenge der Realwerte.
David Hammen
4
@ Kevin: Sie sprechen von den berechenbaren Zahlen, einer winzigen Teilmenge (eine Teilmenge mit dem Maß Null) der Realzahlen.
David Hammen
1
+1 für die grundlegendste Erklärung: Sie versuchen, eine unendliche Anzahl von Zahlen mit einer endlichen Anzahl von Bits darzustellen.
Raku
1
@DavidHammen: Berechenbare Zahlen sind eine winzige Teilmenge (von Maß Null) der Realzahlen - aber jede Zahl, mit der Sie jemals in einem Programm arbeiten, ist per Definition berechenbar.
Keith Thompson
3
@Giorgio: Wenn Sie die richtige Darstellung wählen, die Quadratwurzel von 2 ist darstellbare, beispielsweise als Zeichenfolge "√2". (Mein alter HP-48-Rechner konnte genau das, und das Quadrieren dieses Wertes ergab genau das 2.0.) Es gibt nur eine zählbare Unendlichkeit darstellbarer reeller Zahlen für eine endliche Darstellung - aber keine Berechnung kann eine Zahl ergeben, die nicht ist. grundsätzlich darstellbar. In der Praxis wird die Menge der darstellbaren Zahlen durch binäre Gleitkommazahlen drastisch begrenzt, was sich in einer rasanten Geschwindigkeit und einem geringen Speicherplatz im Vergleich zu symbolischen Darstellungen niederschlägt.
Keith Thompson
-2

Das einzige wirklich offensichtliche "Rundungsproblem" bei Gleitkommazahlen, über das ich nachdenke, sind Filter mit gleitendem Durchschnitt:

$$ \ begin {align} y [n] & = \ frac {1} {N} \ sum \ limits_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$

Damit dies ohne die Entstehung von Rauschen funktioniert, müssen Sie sicherstellen, dass das in den aktuellen Samples hinzugefügte $ x [n] $ genau mit dem Wert von $ x [nN] $ übereinstimmt, den Sie in das subtrahieren Zukunft. Wenn dies nicht der Fall ist, ist etwas anderes, als wenn ein kleiner Trottel in Ihrer Verzögerungsleitung stecken bleibt und niemals herauskommt. Das liegt daran, dass dieser Filter mit gleitendem Durchschnitt tatsächlich mit einem IIR aufgebaut ist, der einen geringfügig stabilen Pol bei $ z = 1 $ und eine Null aufweist, die ihn im Inneren aufhebt. Aber es ist ein Integrator und jeder Mist, der integriert und nicht vollständig entfernt wird, wird für immer in der Integratorsumme vorhanden sein. Dies ist der Punkt, an dem Festkommazahlen nicht dasselbe Problem haben wie Gleitkommazahlen.

Robert Bristow-Johnson
quelle
hey, funktioniert $ LaTeX $ math markup nicht im prog.SE forum ??? Das ist wirklich lahm, wenn es nicht so ist.
Robert Bristow-Johnson
1
Siehe dies auf meta.SO und verknüpften Fragen
AakashM