Kaputter COSINUS
-
In einer Funktion hab ich den folgenden Code:
Zu einem Achsparallelem Rechteck 0,0,800,600 (Beispiel)
sollen die Eckpunkte fuer eine Drehung (Beispiel 90°) berechnet werden
Mittelpunkt soll die Mitte sein (Beispiel 400,300){ int PicW,PicH; //Bild- Breite und Hoehe TPoint P1,P2,P3,P4; //4 x Eck- Koordinaten TPoint M; //Mittelpunkt int RotAngle; //Drehwinkel double ArcAng; //Bogenmass zu Drehwinkrl double SinAngle; //sin(ArcAng) double CosAngle; //cos(ArcAng) RotAngle=90; ArcAng=RotAngle * M_PI / 180; SinAngle=sin(ArcAng); CosAngle=cos(ArcAng); //cos(90°) !=0 !!!!! // if (abs(RotAngle->Value)<=90) // CosAngle=sqrt(1 - SinAngle * SinAngle); // else // CosAngle=-sqrt(1 - SinAngle * SinAngle); PicW=800; PicH=600; M.x=PicW / 2; //=400 M.y=PicH / 2; //=300 P1.x=M.x - CosAngle * M.x - SinAngle * M.y; //=100 oder 99 P1.y=M.y - CosAngle * M.y + SinAngle * M.x; //=700 oder 699 P2.x=M.x + CosAngle * (PicW - M.x) - SinAngle * M.y; //=100 P2.y=M.y - CosAngle * M.y - SinAngle * (PicW - M.x); //=-100 P3.x=M.x - CosAngle * M.x + SinAngle * (PicH - M.y); //=700 oder 699 P3.y=M.y + CosAngle * (PicH - M.y) + SinAngle * M.x; //=700 P4.x=M.x + CosAngle * (PicW - M.x) + SinAngle * (PicH - M.y); //=700 P4.y=M.y + CosAngle * (PicH - M.y) - SinAngle * (PicW - M.x); //=-100 oder -99 }Mit den berechneten Werten wird dann ein Bild gedreht (Den Teil hab ich entfernt).
Prinzipiell funktioniert allse (fast) perfekt.PROBLEM:
Bei den Beispielwerten kommen manchmal verschiedene Ergebnisse heraus fuer P1 - P4???
Der Fehler kommt aus der Cos- Funktion!
cos(90°)=6.1257422745E-17FRAGE:
Kann mir einer erklaeren, warum das Ergebnis zufaellig richtig oder falsch 'rundet'.
Beim Casten zu int sollte doch immer dasselbe Ergebnis entstehen.Ich hab fuer beide Faelle mit dem Debugger die angegebenen Werte ermittelt.
'Umschalten' auf die andere Variante erfolgt nach Einstellung einer anderen Farbe mit ColorDialog. Der Dialog und die Variablen haben aber NICHTS mit der Funktion zu tun???
Es scheinen die Werte im RAM die Funktion zu beeinflussen.PS:
Die Werte fuer Breite/Hoehe und Winkel kommen von VCL- Objekten (TImage, CSpinEdit)************************************
Das Problem ist beseitigt, wenn ich die Zeile mit cos(...) durch die auskommentierten Zeile ersetze!
Mich wuerde aber mal das Phaenomen des Zufalles interessieren.Kann das am BCB 4.0 liegen?
-
Prinzipiell bist du dir drüber im Klaren, dass 6.1257422745E-17 eine Zahl mit einer 0 vor dem Komma und dann erstmal ganz vielen Nullen nach dem Komma ist, oder?
Ich würde den Fehler daher eher auf die Ungenauigkeit von Fließkommazahlen tippen. Und wenn du nach int castest, wird immer der nächstkleinere Wert genommen. Vielleicht ist ein exaktes Runden in solch einem Fall angebrachtter?
-
Dasd schrieb:
Prinzipiell bist du dir drüber im Klaren, dass 6.1257422745E-17 eine Zahl mit einer 0 vor dem Komma und dann erstmal ganz vielen Nullen nach dem Komma ist, oder?
?Klar doch!!!
Ich würde den Fehler daher eher auf die Ungenauigkeit von Fließkommazahlen tippen. Und wenn du nach int castest, wird immer der nächstkleinere Wert genommen. Vielleicht ist ein exaktes Runden in solch einem Fall angebrachtter?[/quote]
Deshalb hab' ich ja die Winkelfunktionen rausgenommen.
Das Phaenomen ist ja, dass NICHT IMMER der nächstkleinere Wert genommen wird!!!
Es kommen BEI GLEICHEN Eingangswerten z.T. verschiedene Werte raus!Wenn Winkelfunktionen ungenau rechnen, sollten die das aber doch IMMER GLEICH falsch tun!
-
... der Compiler erwarten an solchen Stellen mitunter ein expliztest casten also
int x = (int)cos(alpha);
Das Hilft bei deinem Problem mit sicherheit.
-
int x = (int)cos(alpha);
Im Allgemeinen ist es eine schlechte Idee, das Ergebnis einer Winkelfunktion nach int zu casten...
-
Danke fuer Eure Tips!!!

Aber ich suche keine Loesung:
DerAltenburger schrieb:
Das Problem ist beseitigt, wenn ich die Zeile mit cos(...) durch die auskommentierten Zeile ersetze!
Mich wuerde aber mal das Phaenomen des Zufalles interessieren.
Kann das am BCB 4.0 liegen?Mich stoert nur die Zufaelligkeit des Ergebnis bei der 'schlechten' Loesung mit Cos / Sin.
Die Ungenauigkeit beim casten sollte doch bei gleichen Eigangsgroesen gleiche Ergebnisse (Fehler) liefern.Wie macht das der Prozessor???
Ich moechte wissen WIE das moeglich ist.
-
Ich habe mir auch über solche Dinge den Kopf zerbrochen. Beispielsweise ist der Sinus von 45° und einem x-fachen + 45° auch verschieden. Leider wissen wir nicht wie der Sinus oder Kosinus berechnet werden (Reihenentwicklung...???). Vielleicht hilft ein Blick in ein Numerikbuch. Dort gibt es viele Abhandlungen über Rechnerungenauigkeiten.
-
Soweit mir bekannt, geht das mit Reihen:
X - X^3/3! + X^5/5! - X^7/7! +...
1 - X^2/2! + X^4/4! - X^6/6! +...
Deshalb auch die verschiedenen Erg. bei Vielfachen.
Mein Problem ist aber: Fuer ein und denselben Wert sollte IMMER dasselbe herauskommen.
-
Es liegt an der Anzahl der signifikanten Stellen. Der Borland Builder verwendet Intel-Float-Format. Bei Verwendung von double betragen diese 16 Stellen. Alle darauffolgende Zahlen werden ohne Sinn und Verstand angereiht. Ich hoffe diesmal mit meiner Antwort richtig zu liegen.
-
Probiere mal float aus. Dann hast du sicher einen Fehler von ???*10e-7 oder e-8!
-
marco 1977 schrieb:
Es liegt an der Anzahl der signifikanten Stellen. Der Borland Builder verwendet Intel-Float-Format. Bei Verwendung von double betragen diese 16 Stellen. Alle darauffolgende Zahlen werden ohne Sinn und Verstand angereiht. Ich hoffe diesmal mit meiner Antwort richtig zu liegen.
Das is ja total besch***** von Borland. Aber das erklaert das zufaellige Verhalten! Da wird alse im RAM undefiniertes Zeug mitbenutzt!?

Danke, Marco 1977

Genau das wollte ich wissen.
PS: das werd' ich mal mit nem Speicherauszug analysieren.