Java / C: OpenJDK native tanh () Implementierung falsch?

8

Ich habe einige native C-Quelltexte der Java Math-Funktionen durchforstet. Vor allem tanh() , da ich neugierig war zu sehen, wie sie das implementiert haben. Jedoch was ich gefunden überraschte mich:

%Vor%

Wie der Kommentar zeigt, ist die Taylor-Serie von tanh (x) um 0 beginnt mit:

%Vor%

Warum sieht es dann so aus, als hätten sie es implementiert als:

%Vor%

Das ist eindeutig nicht die richtige Erweiterung, und sogar eine schlechtere Annäherung als nur tanh(x) = x (was schneller wäre) zu verwenden, wie durch dieses Diagramm angezeigt:

(Die fett gedruckte Zeile ist die oben angezeigte. Die andere graue ist log(abs(x(1+x) - tanh(x))) . Das Sigmoid ist natürlich tanh(x) selbst.)

Also, ist das ein Fehler in der Implementierung, oder ist das ein Hack, um ein Problem zu beheben (wie numerische Probleme, an die ich nicht wirklich denken kann)? Beachten Sie, dass ich erwarte, dass das Ergebnis beider Ansätze genau das gleiche ist, da es nicht genug Mantisse-Bits gibt, um die Addition 1 + x tatsächlich auszuführen, für x & lt; 2 ^ (- 55).

BEARBEITEN : Ich werde zum Zeitpunkt des Schreibens einen Link zu der Version des Codes hinzufügen, damit Sie später darauf zurückgreifen können.

    
Martijn Courteaux 24.01.2017, 00:50
quelle

1 Antwort

6

Unter den Bedingungen, unter denen dieser Code ausgeführt wird, und unter der Annahme, dass IEEE-754 Gleitkomma-Darstellungen mit doppelter Genauigkeit und Arithmetik verwendet werden, wird 1.0 + x immer auf 1.0 auswerten, also wird x * (1.0 + x) immer ausgewertet %Code%. Der einzige externe (zu der Funktion) beobachtbare Effekt der Durchführung der Berechnung, wie es getan wird, anstatt nur x zurückzugeben, wäre, das IEEE- "ungenaue" Statusflag zu setzen.

Obwohl ich keine Möglichkeit kenne, die FP-Statusflags von Java abzufragen, könnte anderer nativer Code sie möglicherweise abfragen. Wahrscheinlicher als nicht, ist der praktische Grund für die Implementierung jedoch durch diese Bemerkungen in Die Javadocs für x :

  

Um die Portabilität von Java-Programmen sicherzustellen, müssen die Definitionen einiger numerischer Funktionen in diesem Paket dieselben Ergebnisse wie bestimmte veröffentlichte Algorithmen aufweisen. Diese Algorithmen sind in der bekannten Netzwerkbibliothek netlib als Paket "Freedom Distributable Math Library," fdlibm verfügbar. Diese Algorithmen, die in der C-Programmiersprache geschrieben sind, sind dann so zu verstehen, dass sie mit allen Gleitkommaoperationen ausgeführt werden, die den Regeln der Java-Gleitkommaarithmetik folgen.

     

Die Java-Math-Bibliothek ist in Bezug auf fdlibm Version 5.3 definiert. Wenn fdlibm mehr als eine Definition für eine Funktion (z. B. acos) bereitstellt, verwenden Sie die Version "IEEE 754 core function" (die sich in einer Datei befindet, deren Name mit dem Buchstaben e beginnt). Die Methoden, die fdlibm-Semantik erfordern, sind java.StrictMath , sin , cos , tan , asin , acos , atan , exp , log , log10 , cbrt . , atan2 , pow , sinh , cosh , tanh , hypot und expm1 .

(Hervorhebung hinzugefügt.) Sie werden im C-Quellcode ein log1p notieren, das es mit den Javadoc-Kommentaren zu verbinden scheint.

    
John Bollinger 24.01.2017, 06:03
quelle

Tags und Links