JavaScript/Objekte/Math/expm1

Aus SELFHTML-Wiki
< JavaScript‎ | Objekte‎ | Math
Wechseln zu: Navigation, Suche

Die Methode expm1(x) erwartet als Parameter eine Zahl x.

Berechnet wird die Formel ex - 1, also die Potenz von x zur Basis e, vermindert um 1.

Der Sinn dieser Methode ist, dass es bei Verwendung von Math.exp(x) - 1 zu Genauigkeitsverlusten kommen kann, wenn x sehr nahe bei 0 liegt (und ex damit sehr nahe bei 1).

Beispiel
   let grob = Math.exp(1.111112222211111e-13) - 1,
       genau = Math.expm1(1.111112222211111e-13);

   console.log("exp(1.111112222211111e-1) ergibt:");
   console.log("mit exp(x) - 1: ", grob);
   console.log("mit expm1(x) - 1: ", genau);
  }

Das Beispiel berechnet e1.111112222211111∙10-13-1 einmal mit Math.exp und einmal mit Math.expm1. Die Ergebnisse werden zum Vergleich ausgegeben.

Wenn man dem Full Precision Calculator auf mathisfun.com trauen darf, lautet das korrekte Ergebnis 1.1111122222111727285185173479516758...e-13

Signifikanzverlust

Wenn Sie die exp() Methode auf eine Zahl anwenden, die sehr nahe bei 0 liegt (wie im obigen Beispiel), erhalten Sie bei Verwendung eines Prozessors, der das IEE754-double Format verwendet, 1.000000000000111 als Ergebnis. Wenn Ihre weitere Verarbeitung nun so aussieht, dass Sie davon einen Wert subtrahieren müssen, der ebenfalls nahe bei 1 liegt, entsteht das Problem des Signifikanzverlusts. Der wirklich interessante Teil des exp()-Aufrufs hat nämlich nur 3 brauchbare Ziffern. Zieht man davon 1 ab, erhält man 1.1102230246251565e-13, was zum größten Teil Bitrauschen darstellt. Nur die drei ersten Ziffern sind real.

Wichtig: Dieser Wert ist nicht wirklich schlecht. Der absolute Fehler (also Differenz zwischen berechnetem und korrektem Wert) liegt bei 9e-17. Wenn Sie damit leben können, haben Sie kein Problem. Schwierig wird es, wenn Sie auf einen kleinen relativen Fehler angewiesen sind (das Verhältnis der Fehlerabweichung zum korrekten Wert), denn der liegt hier bei ca 0.1%.

Ihr Prozessor verwendet eine in Silizium gebrannte mathematische Formel, um exp(x) zu berechnen. Dabei handelt es sich um ein Polynom, das mit Hilfe der sogenannten Taylor-Entwicklung der ex-Funktion entstanden ist. Das Ergebnis ist im Rahmen der verfügbaren Bits in der Fließkommaeinheit des Prozessors auf 16 Stellen genau (der Prozessor rechnet intern mit ein paar Bits mehr). Gegen Sonderfälle wie den oben beschriebenen nützt das aber nichts. Die expm1() Funktion verwendet ein anderes Polynom, für das von vorneherein die Taylor-Entwicklung von ex - 1 zu Grunde gelegt wird. Dadurch ist das Ergebnis sofort in der Nähe von 0 und der Signifikanzverlust findet nicht statt.

Math.expm1(1.111112222211111e-13) ergibt 1.1111122222111727e-13, was in allen Stellen genau ist.

exp oder expm1?

Welche Funktion soll man nun besser verwenden, wenn bei exp() doch solche Probleme drohen. Wie immer lautet die Antwort: Es kommt darauf an. Sie müssen Ihre Berechnungen kennen und die Werte, die in ihrem Verlauf auftauchen. Die expm1()-Funktion ist kein Allheilmittel. Wenn Sie ihr einen Wert nahe 0.6931471805599453 (ln 2) übergeben, bekommen Sie von expm1() einen Wert nahe 1 zurück, und wenn Sie davon 1 abziehen, ist das Problem wieder da. Im Normalfall genügt also der Einsatz von exp() - und nur dann, wenn Sie

  • Werte nahe 0 übergeben
  • Einen Wert nahe 1 davon abziehen
  • und einen kleinen relativen Fehler brauchen

lohnt sich eine Abfrage, ob x nahe bei 0 liegt und ein Wechsel auf expm1().

Siehe auch

  • Math.exp() für die Funktion ex
  • pow(a,x) für die Berechnungen von beliebigen Potenzen ax
  • log(x) für die Berechnung der natürlichen Logarithmus, der Umkehrfunktion zu Math.exp()