Arkustangens
-
Die for-Schleife muss bei 1 anfangen.
(Das Element 0 benutzt du schon bei der initialisierung)Und die Rückgabewerte musst du noch skalieren
result=(float)((180.0 * -winkel)/(0x7FFFFFFFL));
-
Ich habe die Skalierung in der main vorgenommen. Habe deinen Vorschlag eingebaut, jedoch kommt nach wie vor ein falscher Wert heraus.
WinkelA= 0.000000 | WinkelF= -43.254131 | error= 43.254131
WinkelA= 0.099997 | WinkelF= 84.269104 | error= 84.169106
WinkelA= 0.199995 | WinkelF= 78.535240 | error= 78.335243
WinkelA= 0.299993 | WinkelF= 72.809349 | error= 72.509354
WinkelA= 0.399990 | WinkelF= 67.076645 | error= 66.676651
WinkelA= 0.499989 | WinkelF= 61.349762 | error= 60.849773
WinkelA= 0.599987 | WinkelF= 55.623222 | error= 55.023235
WinkelA= 0.699987 | WinkelF= 49.897209 | error= 49.197224
WinkelA= 0.799986 | WinkelF= 44.158195 | error= 43.358208
WinkelA= 0.899986 | WinkelF= 38.432198 | error= 37.532211
WinkelA= 0.999985 | WinkelF= 32.698338 | error= 31.698353
WinkelA= 1.099985 | WinkelF= 26.971798 | error= 25.871813
WinkelA= 1.199985 | WinkelF= 21.245785 | error= 20.045799
WinkelA= 1.299985 | WinkelF= 15.512209 | error= 14.212224
WinkelA= 1.399986 | WinkelF= 9.786195 | error= 8.386209
WinkelA= 1.499986 | WinkelF= 4.059656 | error= 2.559670
WinkelA= 1.599987 | WinkelF= -1.667833 | error= 3.267820
WinkelA= 1.699988 | WinkelF= -7.395354 | error= 9.095342
WinkelA= 1.799989 | WinkelF= -13.135355 | error= 14.935344
WinkelA= 1.899990 | WinkelF= -18.867949 | error= 20.767939
-
WinkelA ist der Wert der math.h atan2 Funktion, WinkelF ist der Wert den meine Funktion zurückliefert.
-
Mit welchen Werten rufst du denn die Funktionen auf?
Zeig doch mal die Funktion, mit der du die Ausgabe ("WinkelA= 0.000000 | WinkelF= -43.254131 | error= 43.254131 ") machst.
-
Also diesen Aufruf erzeuge ich über ein Textfile
fprintf(ATANFILE,"WinkelA= %f|WinkelF= %f|error= %f\n",atan2(mysin,mycos),winkelF,error);
Der Funktionsaufruf für atan2 : winkelF = (i_atan2(mysin2,mycos2));
mysin und mycos werden in einer anderen Funktion berechnet und anschließend für atan2 in integer umgewandelt.mysin2 = (int)(mysinPOW_31_MINUS_1);
mycos2 = (int)(mycosPOW_31_MINUS_1);In der main läuft eine for-Schleife, die mir 20 Sinus/Cosinus Werte und daraus atan2 Werte berechnet.Hier doch besser die main:
int main() { int i; int mysin2,mycos2; float angle=0,error=0.0; float mysin,mycos,arctan,winkelF=0.0; ATANFILE=fopen("atan.txt","w"); for(i=0;i<20;i++) { mysin = sinF(angle); mycos = cosF(angle); mysin2 = (int)(mysin*POW_31_MINUS_1); mycos2 = (int)(mycos*POW_31_MINUS_1); winkelF = (i_atan2(mysin2,mycos2)); error = fabs(winkelF-atan2(mysin,mycos)); fprintf(ATANFILE,"WinkelA= %f | WinkelF= %f | error= %f \n",atan2(mysin,mycos),winkelF,error); angle += 0.1; } fclose(ATANFILE); return 0; }
-
mysin/mycos liefert Werte zwischen -1 und 1
-
DirkB schrieb:
Beachte aber auch die Reihenfolge der Parameter von der Funktion (atan2) aus der Standardbibliothek.
Du solltest es nicht anders machen.Der Prototyp von atan2 aus der math.h lautet
double atan2 ( double y, double x );
Deine Funktion:
float i_atan2(int x,int y)
DirkB schrieb:
Winkel werden bei Computern meist/oft/häufig im Bogenmaß angegeben.
Du scheinst aber mit Grad zu rechnen.
Wofür ist der Algorithmus denn ausgelegt.atan2 aus der math.h gibt Bogenmaß zurück.
Bei der Umrechnung, die ich geschrieben habe, habe ich Grad verwendet, da Bogenmaß mit int nicht sehr sinnvoll ist.
(Wo ist diese Umrechnung denn jetzt? Du hast geschrieben die sei in der main)Statt POW_31_MINUS_1 kannst du auch 10000 (oder 100000) nehmen.
Interresant sind doch die Werte für 0, 45, 90 ... Grad.
winkelF = (i_atan2( 10000, 0)); // 0 Grad winkelF = (i_atan2( 10000, 10000)); // 45 Grad winkelF = (i_atan2( 0, 10000)); // 90 Grad winkelF = (i_atan2(-10000, 0)); // 180 Grad winkelF = (i_atan2( 0, -10000)); // -90 Grad
-
result=(float)((-winkel)*DIVPOW_31_MINUS_1 *180));
Ich hatte es kurz vorher in die Funktion geschrieben.
atan2(y=cos,x=sin)?
-
MrChipsy schrieb:
result=(float)((-winkel)*DIVPOW_31_MINUS_1 *180));
Ich hatte es kurz vorher in die Funktion geschrieben.
Also Grad.
Wenn du das mit dem Ergebnis von atan2 vergleichen willst, musst du Umrechnen.Aber warum denn jetzt noch DIVPOW_31_MINUS_1 als neue Konstante.
MrChipsy schrieb:
atan2(y=cos,x=sin)?
Einheitskreis
x = cos; y = sinWenn der Y-Wert 0 ist und X positiv (> 0), kommt 0° raus
sin(0°) = 0, cos(0°) = 1Wenn der Y-Wert positiv (> 0) ist und X gleich 0, kommt 90° raus
sin(90°) = 1, cos(90°) = 0
-
mysin2 = (int)(mysin*POW_31_MINUS_1); mycos2 = (int)(mycos*POW_31_MINUS_1);
Das war meine Normierung für Festkomma, um danach wieder auf Fließkomma zu kommen multipliziere ich den Kehrwert von POW_31_MINUS_1.
Macht man das nicht so?
Nach wie vor komme ich nicht auf die Werte
-
WinkelA= 0.000000 | WinkelF= 46.752865 | error= 46.752865
WinkelA= 5.729409 | WinkelF= 5.729409 | error= 0.000000
WinkelA= 11.458842 | WinkelF= 11.458842 | error= 0.000001
WinkelA= 17.188329 | WinkelF= 17.188330 | error= 0.000000
WinkelA= 22.917751 | WinkelF= 22.917751 | error= 0.000000
WinkelA= 28.647286 | WinkelF= 28.647287 | error= 0.000001
WinkelA= 34.376748 | WinkelF= 34.376751 | error= 0.000003
WinkelA= 40.106289 | WinkelF= 40.106289 | error= 0.000000
WinkelA= 45.835820 | WinkelF= 45.835823 | error= 0.000003
WinkelA= 51.565372 | WinkelF= 51.565372 | error= 0.000000
WinkelA= 57.294938 | WinkelF= 57.294937 | error= 0.000001
WinkelA= 63.024476 | WinkelF= 63.024479 | error= 0.000003
WinkelA= 68.754089 | WinkelF= 68.754089 | error= 0.000000
WinkelA= 74.483655 | WinkelF= 74.483658 | error= 0.000003
WinkelA= 80.213275 | WinkelF= 80.213280 | error= 0.000005
WinkelA= 85.942875 | WinkelF= 85.942871 | error= 0.000003
WinkelA= 91.672488 | WinkelF= 91.672493 | error= 0.000005
WinkelA= 97.402108 | WinkelF= 97.402115 | error= 0.000007
WinkelA= 103.131742 | WinkelF= 103.131744 | error= 0.000003
WinkelA= 108.861382 | WinkelF= 108.861382 | error= 0.000001So es klappt jetzt, großes Dankeschön an dich!
Muss jetzt nur noch schauen, dass ich den ersten Wert hinbekomme.
-
Für die Berechnung des atan2 spielt es keine Rolle ob du bei x und y jetzt OW_31_MINUS_1 oder 100000 hast. Hauptsache beide Werte sind gleich skaliert.
Und auch der atan2 aus der math.h kann die selben Werte bekommen.Da cos(0) = 1 ist, kann es sein dass du mit deinen OW_31_MINUS_1 an die Grenze des Algorithmus kommst. Versuch es doch mal mit 100000.
Nebenbei werden alle Fließkommeberechnungen vom Compiler als double ausgeführt.
Es hat eigentlich nur Nachteile float statt double zu nehmen.