Genauigkeit von Math.Sin () und Math.Cos () in C #

7

Ich bin sehr genervt von der Ungenauigkeit der intrinsischen Triggerfunktionen in der CLR. Es ist wohl bekannt, dass

%Vor%

statt 0. Ähnliches passiert mit Math.Cos(Math.PI/2) .

Aber wenn ich eine lange Reihe von Berechnungen mache, die in speziellen Fällen zu

ausgewertet werden %Vor%

und das Ergebnis ist Null für x = 0.2, aber nicht Null für x = 0.1 (versuchen Sie es). Ein anderes Problem ist, wenn das Argument eine große Zahl ist, wird die Ungenauigkeit proportional groß.

Ich frage mich also, ob jemand eine bessere Darstellung der trigonometrischen Funktionen in C # programmiert hat, um sie mit der Welt zu teilen. Ruft die CLR eine Standard-C-Mathematikbibliothek auf, die CORDIC oder etwas Ähnliches implementiert? Link: Wikipedia CORDIC

    
ja72 14.07.2010, 19:25
quelle

5 Antworten

2

Sie müssen eine Dezimalbibliothek mit beliebiger Genauigkeit verwenden. (. Net 4.0 hat eine beliebige Integer-Klasse , aber nicht dezimal) .

Ein paar beliebte sind verfügbar:

BlueRaja - Danny Pflughoeft 14.07.2010, 23:21
quelle
18

Dies hat nichts mit der Genauigkeit trigonometrischer Funktionen zu tun, sondern mehr mit dem CLS-System. Laut der Dokumentation hat ein double eine Genauigkeit von 15-16 Stellen (was genau was du bekommst), damit du mit diesem Typ nicht präziser sein kannst. Wenn Sie also mehr Präzision wünschen, müssen Sie einen neuen Typ erstellen, der sie speichern kann.

Beachten Sie auch, dass Sie niemals einen Code wie diesen schreiben sollten:

%Vor%

Sie sollten stattdessen tun:

%Vor%     
Darin Dimitrov 14.07.2010 19:35
quelle
9

Ich höre dich. Ich bin sehr genervt von der Ungenauigkeit der Teilung. Neulich habe ich:

%Vor%

und ich habe ,333333333333333, statt der richtigen Antwort, die ist 0,333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 3333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 ...

Vielleicht siehst du jetzt, was das Problem ist. Math.Pi ist nicht gleich pi mehr als 1.0 / 3.0 entspricht einem Drittel. Beide unterscheiden sich vom wahren Wert um ein paar Hundert Billiarden, und deshalb werden alle Berechnungen, die Sie mit Math.Pi oder 1.0 / 3.0 durchführen, auch um ein paar Hundert Quadrillionths abweichen, einschließlich des Sinus.

Wenn Sie nicht mögen, dass approximative Arithmetik approximate ist, verwenden Sie keine approximative Arithmetik. Verwenden Sie genaue Arithmetik. Ich benutzte Waterloo Maple, wenn ich genaue Arithmetik benötigte; vielleicht sollten Sie eine Kopie davon kaufen.

    
Eric Lippert 14.07.2010 22:48
quelle
6

Dies ist ein Ergebnis der Fließkomma-Genauigkeit. Sie erhalten eine bestimmte Anzahl von signifikanten Ziffern, und alles, was nicht genau dargestellt werden kann, wird angenähert. Zum Beispiel ist Pi keine rationale Zahl, und daher ist es unmöglich, eine exakte Darstellung zu erhalten. Da du keinen exakten Wert von Pi erhalten kannst, wirst du keine genauen Sinus und Kosinus von Zahlen einschließlich Pi erhalten (noch wirst du die genauen Werte von Sinus und Kosinus die meiste Zeit erhalten).

Die beste Zwischenerklärung ist "Was jeder Informatiker über Fließkomma-Arithmetik wissen sollte" . Wenn Sie nicht darauf eingehen wollen, denken Sie daran, dass Fließkommazahlen in der Regel Näherungen sind, und dass Fließkommaberechnungen wie das Verschieben von Sandhaufen auf dem Boden sind: Mit allem, was Sie damit machen, verlieren Sie ein wenig Sand und ein wenig Schmutz aufheben.

Wenn Sie eine exakte Darstellung wünschen, müssen Sie sich ein symbolisches Algebra-System suchen.

    
David Thornley 14.07.2010 19:53
quelle
1

Ich lehne die Idee ab, dass die Fehler auf Abrundung zurückzuführen sind. Was getan werden kann, ist sin(x) wie folgt zu definieren, indem eine Taylor-Erweiterung mit 6 Termen verwendet wird:

%Vor%

Der typische Fehler ist 1e-16 und der schlimmste Fall ist 1e-11 . Es ist schlechter als die CLR, aber es ist kontrollierbar durch Hinzufügen von mehr Termen. Die gute Nachricht ist, dass die Antwort für die Sonderfälle im OP und für Sin(45°) genau ist.

    
ja72 27.06.2012 04:07
quelle

Tags und Links