Forum: Mikrocontroller und Digitale Elektronik Sinusfunktion in C gut implementiert?


von hubert (Gast)


Lesenswert?

Hallo Forum,

da ich Zeitkritisch den Sinus berechnen muss (<200 Takte),
habe ich mir überlegt den Sinus so zu implementieren:

Was haltet ihr von dieser Methode?
1
#define AnzahlinTabelle  eineZahlXY 
2
.
3
.
4
.
5
.
6
signed char sinus(unsigned char p){
7
  if(p>AnzahlinTabelle*2){  //  >180Grad?
8
    return -sinus(p-(AnzahlinTabelle*2));
9
  }
10
  if(p>AnzahlinTabelle){
11
    return sinus((AnzahlinTabelle*2) - p); //175grad => 180-175=05 
12
  }
13
  return tabelle[p];
14
}

-hub

von Falk B. (falk)


Lesenswert?

@ hubert (Gast)

>da ich Zeitkritisch den Sinus berechnen muss (<200 Takte),
>habe ich mir überlegt den Sinus so zu implementieren:

>Was haltet ihr von dieser Methode?

Gut, kann man aber noch auf 1/4 von 2*Pi reduzieren. Man hat dann halt 4 
Fallunterscheidungen.

MFG
Falk

von yalu (Gast)


Lesenswert?

Wenn die Berechnung zeitkritisch ist, würde ich auf die Rekursion
verzichten und die Unterteilung der Werte in die vier Quadranten
explizit hinschreiben:
1
signed char sinus(unsigned char p){
2
  if(p>AnzahlinTabelle*3)
3
    return -tabelle[AnzahlinTabelle*4-p];
4
  if(p>AnzahlinTabelle*2)
5
    return -tabelle[p-AnzahlinTabelle*2];
6
  if(p>AnzahlinTabelle)
7
    return tabelle[AnzahlinTabelle*2-p];
8
  return tabelle[p];
9
}

Oder natürlich, wenn genug Speicher da ist, die Tabelle so groß
machen, dass sie alle vier Quadranten umfasst.

von Falk B. (falk)


Lesenswert?

@ yalu (Gast)

>Wenn die Berechnung zeitkritisch ist, würde ich auf die Rekursion
>verzichten und die Unterteilung der Werte in die vier Quadranten
>explizit hinschreiben:

Fast richtig. Aber bei dir dauert die Funktion für verschiedene 
Quadranten unterschiedlich lang. Besser so. Binärer Baum.

[c]
signed char sinus(unsigned char p){
  if(p>AnzahlinTabelle*2) {
    if(p>AnzahlinTabelle*3)
      return -tabelle[AnzahlinTabelle*4-p];
    else
      return -tabelle[p-AnzahlinTabelle*2];
  }
  else {
  if(p>AnzahlinTabelle)
    return tabelle[AnzahlinTabelle*2-p];
  else
    return tabelle[p];
  }
}
[c]

>Oder natürlich, wenn genug Speicher da ist, die Tabelle so groß
>machen, dass sie alle vier Quadranten umfasst.

Das kann ja jeder ;-)

MFG
Falk

von yalu (Gast)


Lesenswert?

Hast recht. Damit ist die Berechnung im worst Case eine Abfrage
schneller. Hatte auch die Idee, aber erst, nachdem ich den Code schon
getippt hatte ;-)

von hubert (Gast)


Lesenswert?

danke für die Antworten!

inzwischen habe ich mich für die Tabellengröße 45 entschieden:
1
signed char tabelle[]={  0,  4,  9, 13, 28, 22, 26, 31, 35,                              39, 43, 48, 52, 56, 60, 64, 67, 71,
2
                        75, 78, 82, 75, 88, 91, 94, 97,100,
3
                       103,105,108,110,112,114,116,118,119,
4
                       121,122,123,124,125,126,126,127,127,127};
5
.
6
.
7
.
8
signed char sinus(unsigned char p){
9
  if(p>90) {
10
    if(p>135)
11
      return -tabelle[180-p];
12
    else
13
      return -tabelle[p-90];
14
  }
15
  else {
16
  if(p>45)
17
    return tabelle[90-p];
18
  else
19
    return tabelle[p];
20
  }
21
}

Das heißt also 180 entspricht dem Vollwinkel(360°).

-hub

von Falk B. (falk)


Lesenswert?

AnzahlinTabelle würde ich aber drin lassen und als #define schreiben. 
Macht den Code einfach wiederverwendbar.

MfG
Falk

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

oder noch besser gleich mit sizeof arbeiten.

Matthias

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
Noch kein Account? Hier anmelden.