Frage von Garrarufa, 55

Java Problem, wieso ist Math.cos(Math.PI * 1.5) nicht 0?

Vielleicht mache ich irgendwo einen Denkfehler, aber sollte das nicht 0 sein?

Expertenantwort
von hypergerd, Community-Experte für Mathematik, 12

3 Einflüsse auf die Genauigkeit:

a) Dein Variablentyp: double ist nur auf etwa 15 Nachkommastellen genau

b) Fehlerfortpflanzung: erst PI (nur 16 statt unendlich viele Stellen) dann Multiplikation dann cos

c) Berechnungsalgorithmus ist nur eine Näherungsformel!

90% aller Programmiersprachen benutzen zur Berechnung die Maschinenbefehle FSIN & FCOS. (intern 80 bit genau)

Neuere Compiler, die auch höhere Maschinenbefehle kennen (SSEx, AVX) sind meist schneller & genauer.

Browser wie der neue Chrome haben was eigenes optimiert.

Je größer die Argumente werden, also sich von 0 entfernen, um so ungenauer wird das Funktionsergebnis!

Der FSIN-Befehl rechnet oberhalb von 9.3e18 nicht mehr, sondern gibt das identische Ergebnis zurück: f(x)=x

Welchen der 3 Algorithmen Dein Java-Interpreter (oder hast Du einen Compiler, der eine EXE erzeugt) verwendet, kannst Du also mit sin(x) mit x  um 

9.2e18...1.31e19 testen:

http://www.gerdlamprecht.de/GrobeFPU_Fehler.htm

Antwort
von PhotonX, 38

Was ist es denn, was ist die Ausgabe?

Kommentar von Garrarufa ,

-1.8369701987210297E-16

Kommentar von Suboptimierer ,

Das ist ein interner Rundungsfehler aufgrund der Beschränktheit der Mantisse bei Fließkommazahlen. pi lässt sich im Rechner nicht exakt darstellen.

Kommentar von PROGRAM4FUN ,

Das Ergebnis ist sehr nah an 0 dran. Die minimale Abweichung kann durch Rundungsfehler durch die Zahlendarstellung zustande kommen.

Kommentar von PhotonX ,

Wie meine Vorredner schon schrieben, das ist für einen Computer nah genug an der Null.

Antwort
von TeeTier, 9

Ich nehme an, das wird der gleiche Grund sein, warum ...

0.3 == 0.1 + 0.1 + 0.1

... dir ein false liefert: Gleitpunktmagie :)

Expertenantwort
von Suboptimierer, Community-Experte für Mathematik, 40

Du musst das Bogenmaß in Gradmaß umwandeln: 

Math.cos(Math.PI * 1.5 * 180/Math.PI)
= Math.cos(1.5*180)

Kommentar von Garrarufa ,

Nein, man braucht Bogenmaß

Kommentar von Suboptimierer ,

? Wie meinst du das? Also wenn Math.cos Bogenmaß erwarten würde, müsste doch 0 heraus kommen. Das kann man leicht am Windowstaschenrechner in der Ansicht "Wissenschaftlich" testen.

Stelle ich den Winkel auf Gradmaß, kommt erst 0 heraus, wenn ich pi * 1,5 in Gradmaß umgewandelt habe.

Math.cos erwartet augenscheinlich Gradmaß. Entweder gibt es noch eine zweite Kosinusfunktion in der Bibliothek, die Bogenmaß als Parameter erwartet oder du musst das Argument ins Gradmaß umwandeln.

Kommentar von Unkreatiiiev ,

Nein, Math.cos(double) erwartet Bogenmaß. Das hat einfach damit zu tun, wie die Kommastellen berechnet werden.

Bei mir ist es "-1.8369701987210297E-16", was gegen 0 geht. Daher ist das schon richtig.

Damit es überall der gleicher Wert ist, gibt's das Schlüsselwort "strictfp".


strictfp class Test {

public static void main(final String[] args) {
final double value = Math.cos(Math.PI * 1.5);

System.out.println(value);
}

}

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten