Hallo zusammen, ich absolviere zur Zeit ein Praktikum und soll eine Code entwickeln bei dem ich einen Sinus bis pi/2 berechne und davon auf die Restwerte in den anderen Intervallen schließen soll. Es soll eine Variable vorkommen mit der man angeben kann, wie häufig der Sinus im ersten Intervall abgetastet werden soll. Die kompletten Werte sollen im Anschluss in einem Array gespeichert werden. Kann mir jemand sagen wie ich vom ersten Intervall auf die restlichen Werte kommen kann? Code-Hilfe wäre auch nicht schlecht:) Vielen Dank schonmal
F. B. schrieb: > Kann mir jemand sagen wie ich vom ersten Intervall auf die restlichen > Werte kommen kann? hast du dir mal einen sinus angeschaut? Wenn das 1/4 bekannst ist, dann ist der rest nur eine Spiegelung.
>Code-Hilfe wäre auch nicht schlecht:)
Selbst ist der Mann ;-)
Du kannst z.B. eine Look-UP-Table anlegen und abhängig von Deiner
gewünschten Abtastrate interpolieren. Stichwort DDS.
Oder Du benutzt den CORDIC Algorithmus um beliebig genau Deine Werte zu
berechnen.
Ein grenzstabiles Filter wäre auch möglich.
MyName schrieb: > Selbst ist der Mann ;-) > > Du kannst z.B. eine Look-UP-Table anlegen und abhängig von Deiner > gewünschten Abtastrate interpolieren. Stichwort DDS. > > Oder Du benutzt den CORDIC Algorithmus um beliebig genau Deine Werte zu > berechnen. > > Ein grenzstabiles Filter wäre auch möglich. Käse. So wie ich die Aufgabe verstehe, ist sin in [0,π/2] gegeben, etwa durch math.h von ANSI-C, und daraus sollen dann die fehlenden Funktionswerte erhalten werden.
F. B. schrieb: > Hallo zusammen, > ich absolviere zur Zeit ein Praktikum und soll eine Code entwickeln bei > dem ich einen Sinus bis pi/2 berechne und davon auf die Restwerte in den > anderen Intervallen schließen soll. > Es soll eine Variable vorkommen mit der man angeben kann, wie häufig der > Sinus im ersten Intervall abgetastet werden soll. > Die kompletten Werte sollen im Anschluss in einem Array gespeichert > werden. > Kann mir jemand sagen wie ich vom ersten Intervall auf die restlichen > Werte kommen kann? Code-Hilfe wäre auch nicht schlecht:) > > Vielen Dank schonmal Du sagst es ja schon, DU machst ein Praktikum, also musst du deinen Grips auch selber anstrengen. So schlimm es ist ja nicht. Ingo
Johann L. schrieb: > Käse. Aber was für ein Prachtstück ;-) Johann L. schrieb: > So wie ich die Aufgabe verstehe, ist sin in [0,π/2] gegeben, etwa durch > math.h von ANSI-C, und daraus sollen dann die fehlenden Funktionswerte > erhalten werden. Dann wäre es ja nur: 1) Tabelle vorwärts durchlaufen 2) Tabelle rückwärts durchlaufen 3) Tabelle vorwärts durchlaufen und *(-1) nehmen 4) Tabelle rückwärts durchlaufen und *(-1) nehmen
Ich habe es jetzt so gemacht, dass ich zuerst die Werte bis PI/2 berechnet und in ein Feld abgelegt habe. Hierfür habe ich in einer Schleife folgende Funktion ausgeführt: sin_tab_table[n]= (sin(x)/TAB_SIZE)*PIDIV2; Die restlichen Werten ergeben sich wie zuvor von MyName beschrieben. Es gibt allerdings das große Problem das die Werte bis PI/2 falsch sind. Ist meine Gleichung falsch oder liegt es an falschen Datentypen?
F. B. schrieb: > Ist meine Gleichung falsch oder liegt es an falschen Datentypen? wir sehen keine Datentypen.
sin() ist die Sinus Funktion aus der math.h von c, TAB_SIZE und PIDIV2 sind per #define festgelegt.
F. B. schrieb: > sin() ist die Sinus Funktion aus der math.h von c, TAB_SIZE und PIDIV2 > sind per #define festgelegt. und wie genau sieht das define aus - ja vermutlich ist dort der fehler denn: 0.122/4 = 0 0.122/4.0 = 0.0305
sorry - vergesst mein letzen post, das beispiel ist unsinn 10/4 = 4 10/4.0 = 2.5
Die defines sind so angelegt: #define TAB_SIZE 128 #define PI 3.14159265f #define PIDIV2 PI/2
Sollte von den Datentypen her passen. sin() ist eh als double definiert, also sollte auch die gesamte Berechnung automatisch in diesem Datentyp ausgeführt werden.
aber die formel versteht ich nicht
> sin_tab_table[n]= (sin(x)/TAB_SIZE)*PIDIV2;
wie wird dann n und x gebildet?
zeigt doch mal den completten code.
void sin_tab_init(sin_tab_struct* s_sin,sin_tab_struct* s_cos) { int n; float x=0; memset((void*)s_cos,0,sizeof(sin_tab_struct)); memset((void*)s_sin,0,sizeof(sin_tab_struct)); for(n=0;n<=TAB_SIZE;n++){ sin_tab_table[n]= (sin(x)/TAB_SIZE)*PIDIV2; x++; } } Das ist der Teil, der mir eigentlich meine SinWerte bis PI/2 liefern soll. Dies soll in der Initialisierung erfolgen.
> sin_tab_table[n]= (sin(x)/TAB_SIZE)*PIDIV2;
das ist Unsinn.
Das Ergebnis eines Sinus ist eine Zahl zwischen -1 und +1
x läuft von 0 bis PIDIV2
und nicht das Ergebnis des Sinus wird mit PIDIV2 multipliziert!
wozu sin und cos? sin(x) ist ja wohl unsinn wenn x von 0 bis 128 geth. In der Formel sind die klammern falsch.
F. B. schrieb: > void sin_tab_init(sin_tab_struct* s_sin,sin_tab_struct* s_cos) > { > int n; > float x=0; > > memset((void*)s_cos,0,sizeof(sin_tab_struct)); > memset((void*)s_sin,0,sizeof(sin_tab_struct)); Kannst du dir sparen. Du überschreibst ja soewieso das Feld > for(n=0;n<=TAB_SIZE;n++){ gewöhn dir das <= an dieser Stelle gleich wieder ab. Eine deratige Schleife hat immer die Form for( .. = 0; ... < Anzahl_Elemente; ... ++ ) Immer. Deine Schleife erzeugt (wenn TAB_SIZE zb den Wert 5 hat, eine Tabelle mit 6 Einträgen) > sin_tab_table[n]= (sin(x)/TAB_SIZE)*PIDIV2; x ist der Winkel. Der soll von 0 bis PIDIV2 laufen. Und zwar so, dass wenn n 0 ist, dann soll auch x 0 sein wenn n gleich TAB_SIZE ist, soll x den Wert PIDIV2 ergeben Den Hinweis geb ich dir: Das Ergebnis vom Sinus rechnest du überhaupt nicht mehr um. Das ist direkt der Wert, der in die Tabelle geht. Aber das awas du in den Sinus hineinstopfst, das musst du (ausgehend vom n) entsprechend anpassen und umrechnen. (Aber keine Sorge: Du brauchst nicht mehr als den berühmten Dreisatz: 10 Äpfel kosten 5 Euro 80, wieviel kosten 7 Äpfel?)
Vielen Dank, dein Beitrag hat mir sehr geholfen. Durch deine Erläuterung ging das ganze sehr fix. Es hat allerdings ein wenig länger gedauert, bis ich rausgefunden habe, dass meine Laufvariable n erst gecastet werden muss.Naja jetzt läuft die Berechnung bis PI/2 schonmal richtig.
das memset kannst du dir auch sparen, du überschreibst eh alle werte.
Wie würdet Ihr das Programm weiter aufsetzen? Es geht mir nicht darum wie ich auf die Werte der letzten 3 Quadranten komme, sondern einfach darum wie ich das ganze verpacke. Sollte ich ein weiteres Feld anlegen in welches ich die bereits berechneten+die restliche Werte reinschreibe?
F. B. schrieb: > Wie würdet Ihr das Programm weiter aufsetzen? Es geht mir nicht darum > wie ich auf die Werte der letzten 3 Quadranten komme, sondern einfach > darum wie ich das ganze verpacke. > Sollte ich ein weiteres Feld anlegen in welches ich die bereits > berechneten+die restliche Werte reinschreibe? das macht nun überhaupt keinen sinn. schreibe einfach eine funtion my_sin(x) und dieser soll für jedes X den sinus liefern, diese verwendet dann dein array. (und nicht die orginal sin funktion) dann das gleich für cos, da nutzt du aber auch die my_sin funktion.
Ich sollte die Berechnung nochmal mit Bit-Verschiebung durchziehen. ´Daraus entstand: float sin_tab_mysin(float eps) { unsigned int quadrant, eps1,eps2, idx; float ret; // quadrant = 00 --> 1. Quadrant // quadrant = 01 --> 2. Quadrant // quadrant = 10 --> 3. Quadrant // quadrant = 11 --> 4. Quadrant eps2=(int)(eps+0.5); quadrant = (eps2 & 0xC0000000) >> 30; eps1 = eps2 & 0x3FFFFFFF; if(quadrant & 0x1) eps1 = 0xF0000000 - eps1; // 0 < eps1 < 0x80000000 idx = eps1 >> (30 - 7); ret = sin_tab_table[idx]; if(quadrant & 0x10) ret = ret*(-1); return ret; } allerdings bekomme ich die falschen Werte für den 3 und 4 Quadranten. Hat jemand eine Idee?
F. B. schrieb: > Ich sollte die Berechnung nochmal mit Bit-Verschiebung durchziehen. Offenbar hat dein Winkel 'eps' (wieso eigenlich eps? Ein Winkel heißt Alpha oder Beta, aber nicht eps. eps ist meistens die Abkürzung für Epsilon und der Begriff steht meistens für eine Fehlerschranke) nicht den üblichen Wertebereich in Radianten. > ... nochmal mit Bit-Verschiebung durchziehen. Wozu? Wenn es eine Möglichkeit gibt, Berechnungen durch Bitmanipulationen zu ersetzen UND dies dann auch tatsächlich schneller ist, DANN machen das Compiler seit ungefähr 50 Jahren ganz von alleine. Du gewinnst dadurch nichts. Du schiesst dir damit höchstens ins Knie. > allerdings bekomme ich die falschen Werte für den 3 und 4 Quadranten. > Hat jemand eine Idee? Nimm Werte an, geh deinen Code durch und mach am Papier die gleichen Operationen und sieh dir an, was da passiert. So läuft das nun mal. Du hast es programmiert - du suchst auch die Bugs bzw. du suchst wo du deinen Denkfehler hast. Und im übrigen ist es ja nicht verboten, in seinen Code mal zwischendurch ein paar printf() einzubauen, mit denen man sich Zwischenwerte ausgibt um zu sehen, wie weit die Berechnung mit dem übereinstimmt, was man sich vorstellt.
Ich sitze seit heute morgen davor und komme einfach nicht auf eine vernünftige Lösung, leider geht es so wie oben dargestellt überhaupt nicht richtig. Hast du en Tipp für mich?
F. B. schrieb: > Ich sitze seit heute morgen davor und komme einfach nicht auf eine > vernünftige Lösung, leider geht es so wie oben dargestellt überhaupt > nicht richtig. > Hast du en Tipp für mich?
1 | float sin_tab_mysin(float eps) |
2 | {
|
3 | unsigned int quadrant, eps1,eps2, idx; |
4 | float ret; |
5 | |
6 | // quadrant = 00 --> 1. Quadrant
|
7 | // quadrant = 01 --> 2. Quadrant
|
8 | // quadrant = 10 --> 3. Quadrant
|
9 | // quadrant = 11 --> 4. Quadrant
|
10 | |
11 | printf( "**********************\n" ); |
12 | printf( "eps = %f\n", eps ); |
13 | |
14 | eps2=(int)(eps+0.5); |
15 | quadrant = (eps2 & 0xC0000000) >> 30; |
16 | eps1 = eps2 & 0x3FFFFFFF; |
17 | |
18 | printf( "eps2 = %u, quadrant = %u, eps1 = %u\n", eps2, quadrant, eps1 ); |
19 | |
20 | if(quadrant & 0x1) |
21 | eps1 = 0xF0000000 - eps1; |
22 | |
23 | // 0 < eps1 < 0x80000000
|
24 | idx = eps1 >> (30 - 7); |
25 | |
26 | printf( "idx = %u\n" ); |
27 | |
28 | ret = sin_tab_table[idx]; |
29 | |
30 | printf( "aus Tabelle: %f\n", ret ); |
31 | |
32 | if(quadrant & 0x10) |
33 | {
|
34 | printf( "Quadranten Vorzeichen Korrektur!\n" ); |
35 | ret = ret*(-1); |
36 | }
|
37 | |
38 | printf( "Nach Quadrant korrigiert: %f\n", ret ); |
39 | |
40 | return ret; |
41 | }
|
Lass es laufen, schieb deine Testzahlen durch und studiere den generierten Output. Welche Zwischenwerte sind falsch? Wie sollten sie sein? Wie sind sie statt dessen? 5 Stunden lang den Code anstarren bringt nichts. Du brauchst Fakten! Und dazu brauchst die wiederrum konkrete Zahlenwerte im konkreten Fehlerfall. NB: if(quadrant & 0x10) Sicher, dass du da ein HEX 10 benutzen willst? Welche Werte kann deine Variable 'quadrant' annehmen? Ich denke nämlich, was du in Wirklichkeit wolltest ist if(quadrant > 1) aber durch deine 'Ich muss mit Bitoperationen arbeiten'-Manie hast du dir ordentlich selber ins Knie geschossen. Du bist nicht der erste.
F. B. schrieb: > ich absolviere zur Zeit ein Praktikum und soll eine Code entwickeln bei > dem ich einen Sinus bis pi/2 berechne und davon auf die Restwerte in den > anderen Intervallen schließen soll. Was für Restwerte ? Offen gesagt, ich verstehe aus deinen Worten nicht, was du da eigentlich anstellen willst/sollst. Wenn es darum geht, den Sinus nicht nur für Argumente 0..90°, sondern auch für beliebige andere Winkel zu berechnen, dann würde ich empfehlen, ins Schulbuch zu schauen. Wenn es jedoch darum ginge, aus einem Argument tatsächlich den Sinus zu berechnen und nicht bloß ne Bibliotheksfunktion aufzurufen, dann schau dir mal den Algorithmus nach Pedersen an, den hab ich neulich hier schon mal gepostet. F. B. schrieb: > Es soll eine Variable vorkommen mit der man angeben kann, wie häufig der > Sinus im ersten Intervall abgetastet werden soll. Mein junger Freund, ich rat Euch drum, zuerst Collegium Logicum. Da wird der Geist Euch wohl dressiert, in spansche Stiefel eingeschnürt, daß er bedächgen Schritts fortan hinwandle die Gedankenbahn, und nicht etwa die Kreuz und Quer irrlichteliere hin und her. Irgendwie find ich Mephisto sympathisch. Im Klartext: Lerne erstmal klar zu denken und dann klar deine Gedanken zu formulieren, sonst wird nix draus. Das gilt sowohl für das Schreiben in einem Forum wie diesem als auch noch viel stärker beim Gebrauch einer Programmiersprache. W.S.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.