Probleme mit "ungenauer" Sinusberechnung
-
Sel schrieb:
Wenn mein billger Taschenrechner aus Schulzeiten das hinbekommt, muss es doch auch ne komfortabler Lösung unter C++ geben.
Jaja, der rechnet auch nur gerundete Werte aus...
Bye, TGGC
-
Sel schrieb:
Ich habs schon mit 60 Nachkommastellen probiert und es kommt nicht richtig raus.
"Richtig" liegt hier wohl im Auge des Betrachters

Das "Problem" ist, dass man sich mit Fließkommazahlen sehr sehr weit an 0 annähern kann, nur der Exponent bildet die Grenze. Also 10^-200 ist überhaupt kein Problem.
Du kannst dich aber nicht soweit an 1 annähern (du sagtest, der cos(0) wär genau), da hier die Anzahl der signifikanten Stellen ins Spiel kommt. Es ist da eben 1,0000000001*10^0 und nicht 1 + 10^-9 ... demzufolge ist die Angabe 1 als Ergebnis im Grunde ungenauer als das, was du beim sin(0) rauskriegst.Wenn mein billger Taschenrechner aus Schulzeiten das hinbekommt, muss es doch auch ne komfortabler Lösung unter C++ geben.
Hast du mal dran gedacht, dass der vielleicht einfach rundet? Oder 0 als Spezialfall behandelt, damit Schüler keine Panik kriegen?

-
Danke für die Links, aber da war nichts bei. Bei google habe ich auch schon gesucht.
Vielleicht sollte ich mal an Casio schreiben und fragen wie die das machen
.
-
Hatte die neue Nachricht noch nicht gesehen.
Das Problem mit der genaueren/ungenaueren Berechnung von C++ ist, dass dadurch bei mir völlig falsche Werte rauskommen, die das gesamte Programm sozusagen "sabotieren".
Aber vielleicht kennt ihr eine bessere Lösung.
Das Grundproblem ist folgendes. Es geht mal wieder um das Farbmodell HSI ;-).
Es gibt ein 2 Dimensionales Feld mit, nenen wir es HSI-Pixeln Werten.
Nebeneinanderliegende Pixel werden, wenn sie ein gewisses Kriterium erfüllen (Distanz des Farbwertes zum Beispiel) zu Regionen zusammengefasst.
Wenn jetzt ein Pixel zu einer Region hinzugefügt wird, dann muss man den Mittelwert von H, S, I bilden (also Aktualisierung der Mittelwerte).Von S und I ist das kein Problem. Da H ein Winkel ist wird der Mittelwert folgendermaßen berechnet.
A = Summe aller cos(H)
B = Summe aller sin(H)
Mittelwert von H = atan( B / A);H ist normalerweise im Bereich von 0 bis 360 grad.
Kurioses Phänomen, wenn ich oben genannte Formeln mit meinem Taschenrechner der auf grad eingestellt ist mit rad Werten rechne kommt immer das richtige raus. Wenn jemand weiß, warum das so ist und wie man den Effekt in C++ nachstellen kann werd ich vor Freude explodieren
.Wenn ich es mit grad werten rechne, muss ich ganz normal berücksichtigen in welchem Quadranten des Einheitskreises ich mich befinde und basierend darauf die Berechnung anpassen.
In C++ ist jetzt schon mal das Problem, dass von -pi bis +pi gerechnet wird, man also den H Wert schon mal grundsätzlich in diesen Bereich transformiern.
Bei jeder Aktualisierung des Mittelwertes von H müssen jetzt wieder Bereichsprüfungen gemacht werden, sowie auf Sonderfälle wie 0, 180 und -180 geprüft werden (bzw. 0, pi, -pi). Die Sonderfälle werden aber schon gar nicht erkannt, da wegen (ganz ganz) obigem Problem diese nicht eindeutig abgefragt werden können.
Die Farbmittelwert werden stark verfälscht, was zu weiteren Folgefehlern führt usw.Ich habe da einfach keinen Durchblick mehr, wie man das Problem lösen kann.
-
*dumdidum*
Das Problem lag primär an einer anderen Stelle *erröt*, die mit dem Problem nix zu tun hat. ähem
Aber wenn Euch trotzdem ne elegantere Lösung (für obiges Problem) einfällt, fände ich das super :).
-
Schlechte Nachricht:
Die Sinusfunktion ist eine unendliche Reihe, insofern gibt Dein Taschenrechner und jeder Rechner der Welt, der den Sinus durch eben eine solche Reihe approximiert niemals den genauen Wert an.
Davon abgesehen liegt die Maschinengenauigkeit sowieso bei 10^-16. Was genaueres als das solltest Du nicht erwarten.Und nochwas: Woher weisst Du, dass Dein Taschenrechner immer richtig rechnet und nicht einfach Standardwerte für 0 und 90° etc. benutzt und ansonsten ziemlich miese Approximationen ausspuckt? Woher weisst Du, dass C++ so falsche Werte ausspuckt? Hast Du mal von Hand eine Taylorapproximation von einem willkürlichen Wert (z.B 0.5471) bis zur gewünschten Genuaigkeit berechnet und dann das Deinen Taschenrechner / C++ Programm machen lassen und verglichen?
Gruss
turing
-
du hast 2 probleme: die "ungenauigkeit" von sinus und double. Auf das problem bei der rechnung mit taylorreihen wurde schon eingegangen. Ein weiteres problem ist, dass mit double viele zahlen einfach nicht gut darstellbar sind, also kommt auch hier eine ungenauigkeit ins spiel(liegt nicht am double sondern am dualsystem), damit muss man leben.
Hier ein Beispiel wie man damit leben kann:
double d=5.5;//keine ahnung ob das jetzt eine schlecht darstellbare zahl ist //schlecht if(d==5.5){ //... } //besser if((d-5.5)<=0.00001){//für den genauen wert gabs glaub ich was bei den numic_limits... //... }
-
double d = 5.5; if (d == 5.5) ;Darf keine Probleme machen, denn intern sollte die Maschine wenigstens identische Rundungsfehler machen.
Davon mal abgesehen, wieso brauchst Du eigentlich super genaue Sinus und Cosinus-Werte. Schlussendlich musst Du sie auch wieder speichern und dabei entstehen wieder Fehler.
Gruss
turing
-
@Turing: Das ungenau war schon aus einem Grund in Anführungsstrichen geschrieben, aber das ist wahrscheinlich zu trivial, um von allen verstanden zu werden .... Wie ein anderer Autor hier treffend schrieb, können solche Sachen im Auge des Betrachters liegen, also wäre super wenn mal produktiver Beiträge kommen, als immer wieder die gleiche Korrektur von genau/ungenau.
@all:
"Richtige" Werte war anscheinend irreführend ausgedrückt,
Wenn Du einen Wert nimmst, beispielsweise 155 für H. Dann müsste ja nachdem man die Formeln berechnet hat wieder 155 oder was in der Nähe rauskommen.
Unter C++ muss man jeztz schon mal bei der atan Berechnung berücksichtigen in welchem Quadranten des Einheitskreises H liegt (Sonderfälle sind immer noch 0, pi, -pi).Beim Taschenrechner ist es aber so, dass ich wenn ich ihn auf grad einstelle und mit rad Werten im Bereich von H=0...360 fülle, immer das gewünschte Ergebnis erscheint (ohne Berücksichtigung irgendwelcher Quadranten oder von Sonderfällen). Das ist eigentlich merkwürdig, aber für das was ich will gut. Also frag ich micht, ob man das so nicht auch in C++ hinbekommt und wieso, dass beim Taschenrechner überhaupt so ist.
@otze:
Die Sonderfälle frag ich jetzt als Berech ab. Danke für einen der wenigen produktiven Beiträge.
-
Sel schrieb:
Beim Taschenrechner ist es aber so, dass ich wenn ich ihn auf grad einstelle und mit rad Werten im Bereich von H=0...360 fülle, immer das gewünschte Ergebnis erscheint (ohne Berücksichtigung irgendwelcher Quadranten oder von Sonderfällen). Das ist eigentlich merkwürdig, aber für das was ich will gut. Also frag ich micht, ob man das so nicht auch in C++ hinbekommt und wieso, dass beim Taschenrechner überhaupt so ist.
Kannst du mal die Formeln dafür posten? Das hört sich ja fast so an, als wär die ganze Geschichte mehr oder weniger invariant gegenüber den verwendeten Funktionen

-
Ach so, ne mir ist wieder eingefallen warum es beim Taschenrechner geht. Ihr müsst mir schon verzeihen, ich bin etwas verzweifelt wegen dem Programm und seh den Wald vor lauter Bäumen nicht. Aargh
In dem ich die rad Werte eingebe werden sie vom Taschnrechner natürlich denoch wie grad brechnet. Da da rad Werte von 0..360 erstens eindeutig und zweitens in einen günstigen kleinen Bereich fallen kommt immer das gewünschte/richtige raus.
Unter c++ geht das nicht, weil eh schon mit rad gerechnet wird. Wenn man die jezt noch mal in einen günstigen Bereich normalisiert, ... könnte das .... Muss ich mal länger drüber nachdenken.
Müsst man im Prinzip eine Funktion schreiben, die Sinus und Cosinus mit grad berechnet. Gibt es das schon?
-
Wenn du weißt, wie man rad in grad und umgekehrt umrechnet schon.
-
Ja, das weiß ich. Aber ich seh nicht wie mir das weiterhilft?
-
Sel schrieb:
Ja, das weiß ich. Aber ich seh nicht wie mir das weiterhilft?
Ja überleg doch mal. Du hast ne Funktion die mit rad arbeitet, weißt aber wie man von Grad in rad umrechnet.
-
Ist wahrscheinlich auch zu trivial...
-
Entweder reden wir aneinander vorbei oder ich kapier nicht was ihr mir sagen wollt.
Vielleicht noch mal ganz für doof erklären ??Ich weiß wie ich den Sinus in c++ berechne. Das ist ja nicht mein Problem, sondern, dass man aufgrund der -pi bis +pi Verteiling der Werte immer noch Abfragen muss in welchem Quadranten des Einheitskreises man sich befindet und sich darauf basierend die Rechnung von H Mittelwert : atan( B / A) ändert (dazu kommen halt die viel beschriebenen Sonderfälle).
Ich will die Rechnung aber so haben, dass es keine Sonderfälle gibt (wie es halt mit dem Taschenrechner durch Normalisierung der Werte in einen kleinen Bereich geht).
Ich hab die Lösung auf jeden Fall jetzt glaub ich endlich gefunden. Man erziehlt den gleichen Effekt wie beim Taschnrechner, folgendermaßen:
double d = 360;
d= d * pi / 180;
d= d * pi / 180;Dadurch bringt man die rad Werte in einen ähnlich kleinen Bereich wie bei der Taschnrechner Methode, und alle Berechnung laufen wie von mir gewollt komfortable und einfach ab.
Wenn Ihr mir das sagen wolltet mit Euren Beiträgen dann habe ich es aus Euren Beschreibungen leider nicht verstanden. Nächstes Mal bitte mit der Holzhammermethode erklären.
Vielen Dank für die Aufmerksamkeit
.@Turing: Wenn Du dich nur streiten willst und nichts produktives beizutragen hast, spar Dir doch einfach die Zeit und antworte nicht.
-
Wenn Du dich nur streiten willst und nichts produktives beizutragen hast, spar Dir doch einfach die Zeit und antworte nicht.
Ich finde es nur nicht sehr nett, wie Du antwortest. Schließlich wollte ich nur helfen!
In Zukunkt werde ich mir dann unproduktive Beiträge Dir gegenüber halt sparen...Gruss
turing
-
Er kennt den Unterschied zwichen grad und rad nicht. 
Hab mir schon früher nicht erklären können was mit
Sel schrieb:
In dem ich die rad Werte eingebe werden sie vom Taschnrechner natürlich denoch wie grad brechnet. Da da rad Werte von 0..360 erstens eindeutig und zweitens in einen günstigen kleinen Bereich fallen kommt immer das gewünschte/richtige raus.
oder
Sel schrieb:
Beim Taschenrechner ist es aber so, dass ich wenn ich ihn auf grad einstelle und mit rad Werten im Bereich von H=0...360 fülle, immer das gewünschte Ergebnis erscheint (ohne Berücksichtigung irgendwelcher Quadranten oder von Sonderfällen). Das ist eigentlich merkwürdig, aber für das was ich will gut.
meint. Na dann ist ja jetzt alles gut
Sel schrieb:
Ich hab die Lösung auf jeden Fall jetzt glaub ich endlich gefunden. Man erziehlt den gleichen Effekt wie beim Taschnrechner, folgendermaßen:
double d = 360;
d= d * pi / 180;Ja das stimmt so rechnet man von grad nach rad um.
Kurt
-
Es geht doch gar nicht um die Umrechnung von Rad nach Grad. Wie das geht war schon beim ersten Beitrag des Themas bekannt.

Anscheinend kann man das Problem in nem Forum nicht genau genug erklären.
Das Hauptproblem ist die vernünftige Mittelwertbildung von Winkeln... aber Schwamm drüber.