Hallo,
da ich für ein Problem den Sinus und Cosinus für beliebige Winkel in
hundertstel Grad berechnen müsste und mir da die Wertetabelle zu groß
wird (144kB), suche ich nach einer Möglichkeit den Sinus und Cosinus
"live" zu berechnen. Also wie der Taschenrechner auch.
Kann mir da jemand Tipps oder Rechenformeln geben?
Tabelle einfach kleiner machen und linear oder kubisch interpolieren.
Außerdem reicht es eine viertel Periode in der Tabelle zu halten.
Je nach Qualitätsanforderung ist auch eine Parabelannäherung leicht und
schnell zu realisieren. Vielleicht ist die Taylorreihenentwicklung der
Sin/cos-Funktion eine Option.
Ansonsten halt CORDIC.
Zwei Ideen:
1. Du brauchst ja nur den Sinus von 0..90° in der Tabelle zu halten,
alles
andere ergibt sich aus Quadrantenumrechnung und Verschiebungen.
2. Überlege, welche Genauigkeit notwendig ist. Man kann auch mit
Reihenentwicklung oder wenigen Stützstellen und Interpolation dazwischen
arbeiten.
Ahoi, Martin
"Du brauchst ja nur den Sinus von 0..90° in der Tabelle zu halten,
alles andere ergibt sich aus Quadrantenumrechnung und Verschiebungen"
Da kann man noch weiter sparen, es reicht IMHO 0-45° ;-)
ja an eine C-Code Implementierung der Taylor Reihe habe ich gedacht.
Die Idee in der C Bibliothek nachzusehn ist natürlich nicht schlecht.
Lokal auf meinem Rechner hab ich mal in den math.c files gesucht und
nichts gefunden. Aber mal sehn was sich noch finden lässt.
Bei 0-45° benötigte er dann sin UND cos, es liefe auf denselben Aufwand
hinaus.
Oder sin(x) = sqrt( 1 - (sin(90°-x))^2) ausnutzen. Aufgrund des Aufwands
mit der Wurzel aber auch Käse.
@ 6632 (Gast)
>Den Cosinus kann man aus dem Sinus durch ableiten errechnen. Oder durch>integrieren.
Was ja auch alles sehr einfach und schnell geht . . .
Leute gibts.
Laut
http://www.eng.monash.edu.au/uicee/gjee/vol8no3/Risse.pdf
verwenden Taschenrechner und x86-Prozessoren den CORDIC-Algorithmus,
auch wenn es in der Literatur immer wieder anders behauptet wird.
"Seit 1980 implementiert der 8087, der mathematische Coprozessor des
8086, in Hardware eine Reihe von Konstanten, trigonometrischen und
logarithmischen Funktionen ... Die Indizien sind erdrückend: simple
Taylor- Approximation allein kann diesen Implementierungen nicht
zugrunde liegen!"
Der Hauptvorteil vom CORDIC ist, dass man keine Multiplikationen
braucht, deshalb wird er gerne für Hardwareimplementierungen verwendet.
Wenn man aber sowieso schon einen Multiplizierer im Controller hat ist
Cordic nicht mehr unbedingt die beste Wahl, ich würde auch mal
Polynomapproximation mit Horner-Schema ausprobieren. Wenn die
Geschwindigkeit keine Rolle spielt ist es natürlich das einfachste die
sin-Funktion aus der Compilerbibliothek zu benutzen.
Hallo,
könnte man das wie folgt machen:
Man legt eine Tabelle für sin und cos wie folgt an:
phi_tab sin_tab cos_tab
------------------------------------
PI/4 sin(PI/4) cos(PI/4)
PI/16 sin(PI/16) cos(PI/16)
...
PI/16384 sin(PI/16384) cos(PI/16384)
mit den Additionstheoremen für sin und cos:
sin(x+y) = sin(x)cos(y) + cos(x)sin(y)
cos(x+y) = cos(x)cos(y) - sin(x)sin(y)
kann man sich an den Winkel heranrechnen und ist so theoretisch exakt!
Man kann die Genauigkeit über die Länge der Tabelle bestimmen.
berechne sin(phi) und cos(phi)
Start:
sin = 0
cos = 1
xphi = 0
Schleife i über die Tabelle:
xphi= xphi + phi_tab(i)
if xphi <= phi
temp = sin*cos_tab(i) + cos*sin_tab(i)
cos = cos*cos_tab(i) - sin*sin_tab(i)
sin = temp
else
xphi = xphi - phi_tab(i)
endif
ende Schleife
Mit einem Trick kann man etwas schneller sein:
Man Skaliert den Winkel auf 90Grad (PI/2). Dann sind die Einsen im
Bitmuster für den Winkel die Tabelleneiträge, die für die Näherung
gebraucht werden:
56,25Grad = 45Grad + 11,25Grad = 10100..0
also die Zeilen für PI/4 und PI/16.
Das ganze muss man sich natürlich mal in Fixpunktarithmetik anschauen.
Waldo
Hallo!
Wollte für meine Frage kein extra Thema aufmachen, und ich glaube es
passt hier ganz gut rein... Im Großen und Ganzen geht es auch wieder um
die Berechnung von böden trigonometrischen Funktionen:
In meinem Programm muß ich öffters mit diesen Funktionen rechnen. Und
aufgrund der kritischen Rechenzeit kann ich das nicht "online" machen.
Darum habe ich für Sinus und Cosinus jeweils schon Tabellen mit
stützwerten abgelegt, was dann so aussieht:
for(i = 0; i <= 512; i++)
{
cosinus[i] = ( (int) (128 + 128 * cos((i 2 3.1416) / 512) * 0.99) );
sinus[i] = ( (int) (128 + 128 * sin((i 2 3.1416) / 512) * 0.99) );
}
Im weitern Verlauf werde ich nur mit Festkommazahlen rechnen. Aber das
soll nicht eure Sorge sein ;) . Ich hab nur grad irgendwie ein Problem
mit der Formel für den ARCUS-Sinus und ARCUS-Cosinus. Für die will ich
auch Tabellen anlegen, aber ich komm nicht auf die Formel...
Kann mir die vielleicht jemand unter die Arme greifen?
Danke,
vG,
Jojo
Hallo nochmal und danke für die rasche Antwort!
Hm, jetzt, wo ich das so sehe hätte ich da auch selbst drauf kommen
können ;) ... aber trotzdem danke, manchmal hab ich einfach ein Brett
vor dem Kopf.
Das mit dem Faktor 0,99 hab ich aus einer Formel, die ich im NEtz
gefunden habe. Aber richtig, ob ich sie benutze oder weglasse macht
keinen signifikanten Unterschied.
Jojo schrieb:
> Das mit dem Faktor 0,99 hab ich aus einer Formel, die ich im NEtz> gefunden habe. Aber richtig, ob ich sie benutze oder weglasse macht> keinen signifikanten Unterschied.
Doch, das tut es :-)
Aber es löst ein Problem auf eine etwas seltsame Weise :-)
Mal angenommen es wäre nicht da
Der cos eines Winkels kann minimal -1 sein
128 + ( 128 * -1 ) = 0
aber: er kann maximal +1 sein
128 + ( 128 * 1 ) = 256
Und 256 ist nun mal zu gross für ein Byte :-)