Forum: Mikrocontroller und Digitale Elektronik Berechnung mit cos führt zum Fehler


von CG (Gast)


Lesenswert?

Hallo alle zusammen,

ich habe ein Problem in meinem Sorcecode und würde euch gerne um Hilfe 
bitten.

Zu den Eckdaten:
Ich verwende eienen ATMEGA128 der mit 16MHz läuft und würde gerne 
folgende Gleichung berechnen:
1
 Zeitdifferenz = ( 12*acos( ( sin(h[i]) - sin(B)*sin(DK) ) / (cos(B)*cos(DK)) ) ) / pi;

inludiert ist die math.h
für
h[0] = -0,833
B = 0,91583333
DK = -0,1747629

wenn ich mich nicht verrechnet habe müsste für die Zeitdiferenz 
5,21131484 errechnet werden.
Leider rechnet mein Controller nur Unsinn. Kann es sein das er mit den 
cos(DK) nicht zurecht kommt?

Ach ja die Werte sind alle mit double deklariert.

Würde mich sehr über eure Hilfe freuen.
Vermutlich mache ich einfach was falsch oder habe einen Denkfehler.

Dankeschön schonmal im Voraus.

PS falls noch weintere Eckdaten nützlich sind um das Problem zu lösen 
einfach schreiben. :-)

von Karl H. (kbuchegg)


Lesenswert?

CG schrieb:

>
1
 Zeitdifferenz = ( 12*acos( ( sin(h[i]) - sin(B)*sin(DK) ) / 
2
> (cos(B)*cos(DK)) ) ) / pi;
>
> inludiert ist die math.h
> für
> h[0] = -0,833
> B = 0,91583333
> DK = -0,1747629
>
> wenn ich mich nicht verrechnet habe müsste für die Zeitdiferenz
> 5,21131484 errechnet werden.
> Leider rechnet mein Controller nur Unsinn. Kann es sein das er mit den
> cos(DK) nicht zurecht kommt?

kann ich mir nicht vorstellen.
Was in solchen Sachen immer eine gute Hilfe ist, das ist wenn man den 
Monsterausdruck einfach mal in Teilausdrücke aufdröselt
1
  float cosDK = cos(DK);
2
  ....
und sich die Teilergebnisse ansieht bzw. mit dem Taschenrechner 
vergleicht.

Aber Vorsicht: Im Gegensatz zu der Normaleinstellung eines 
Taschenrechners, rechnet die C Funktion den Winkel in Radianten und 
nicht in Grad! Das ist sogar ein recht häufiger Fehler, dass dieses 
Faktum übersehen wird. Sei es im C-Programm oder sei es bei der 
Kontrolle im Taschenrechner.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Rechnest DU ihn Grad oder Bogenmaß?

von CG (Gast)


Lesenswert?

@Dirk B.
Rechne in Bogenmass

@ Karl Heinz
Das ausrechnen in einzelnen Schritten habe ich auch schon ausprobiert 
und leider kommt auch nicht gescheites dabei raus.

Im Debuger steht unter Zeitdifferenz bei Value n. def.

von Karl H. (kbuchegg)


Lesenswert?

CG schrieb:

> @ Karl Heinz
> Das ausrechnen in einzelnen Schritten habe ich auch schon ausprobiert
> und leider kommt auch nicht gescheites dabei raus.

Was muss ich mir unter 'nichts gescheites' vorstellen?

> Im Debuger steht unter Zeitdifferenz bei Value n. def.

Na ja.
Da ist eine komplexe Berechnung und am Ende kommt 'nicht definiert' 
raus. Ich schätze mal: Division durch 0.0

D.h. nächste Frage: wird tatsächlcih durch 0 dividiert?

Also aufteilen:
1
 float Dividend = sin(h[i]) - sin(B)*sin(DK);
2
 float Divisor = cos(B)*cos(DK);
3
4
 Zeitdifferenz = ( 12*acos( Dividend / Divisor  ) ) / pi;
und die Einzelwerte ansehen bzw. mit dem Taschenrechner verlgeichen.

Es tut mir leid, wenn ich dir nicht so helfen kann, dass ich mit dem 
Finger auf eine Stelle zeige und sage: hier ist der Fehler.
Ich kann dir nur zeigen, wie ich das angehen würde. Alle die mich hier 
kennen wissen sehr wahrscheinlich, dass ich mit der Methode "wenn etwas 
zu komplex ist, dann muss man es eben in einfachere Einheiten zerlegen" 
ganz gut fahre.
Und genau das würde ich auch hier machen. Die Berechnung ist in ihrer 
Gesamtheit komplex und ganz zum Schluss kommt Unsinn raus. Ergo zerleg 
ich die eben in Teile und sieh mir die Teile an. Wenn feststeht, welcher 
dieser Teile für den Unsinn verantwortlich ist, dann zerleg ich den 
wieder weiter. Solange bis ich bei der eigentlichen Ursache angelangt 
bin.

So würde ich das angehen. Du magst das gerne anders halten. Aber sich 
hinstellen und sagen "zum Schluss kommt n.def raus - was könnte die 
Ursache sein", bringt dich nicht weiter.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Da ist eine komplexe Berechnung und am Ende kommt 'nicht definiert'
> raus. Ich schätze mal: Division durch 0.0

Der acos könnte auch die Ursache sein.
Dividend / Divisor muss im Bereich -1.0 bis +1.0 sein, damit der acos 
definiert ist. Schon ein ganz klein wenig drüber .... und das Ergebnis 
ist nicht mehr definiert.

Also: Was ergibt
1
  float Dividend = sin(h[i]) - sin(B)*sin(DK);
2
  float Divisor = cos(B)*cos(DK);
3
  float Quotient = Dividend / Divisor;
4
 
5
  Zeitdifferenz = ( 12*acos( Quotient  ) ) / pi;

Welchen Wert hat Quotient?

von Karl H. (kbuchegg)


Lesenswert?

PS. die math.lib hast du aber schon eingebunden?

von Josef (Gast)


Lesenswert?

Mit deinen angegebenen Zahlen kommt fuer

( sin(h[0]) - sin(B)*sin(DK) ) / (cos(B)*cos(DK)) ) = -1.00368

raus.

Der ACos(...) davon gibt eine komplexe Zahl.

Das willst du aber wahrscheinlich gar nicht, sondern zuvor
auf den Bereich  -1 <= x <= 1 pruefen.

etc.

PS: Ich nehme an du programmierst die Zahlen schon mit Punkt (-0.833) 
und nicht mit Komma (-0,833).

Gruss

von arccos (Gast)


Lesenswert?

Karl Heinz schrieb:
> Also: Was ergibt  float Dividend = sin(h[i]) - sin(B)*sin(DK);
>   float Divisor = cos(B)*cos(DK);
>   float Quotient = Dividend / Divisor;
>
>   Zeitdifferenz = ( 12*acos( Quotient  ) ) / pi;
>
> Welchen Wert hat Quotient?

-1,00367807120192 --> acos nicht definiert

von CG (Gast)


Lesenswert?

so ich habe das mal komplett aufgesplittet
1
double x1 = cos(B)*cos(DK);
2
double x2 = sin(B)*sin(DK);
3
double x3 = sin(h[i]);
4
double x4 = x3 - x2;
5
double x5 = x4 / x1;
6
double x6 = acos(x5);
7
double x7 = 12 * x6;
8
double x8 = x7 / pi;

Ergebnisse:
x1 = 0,599
x2 = -0,137
x3 = -0,7399
x4 = -0,6019
x5 = -1,004166 -> denke hier ist dann das Problem

würdest du dann bei x5 schauen ob der wert kleiner ist als -1 und diesen 
dann auf -1 setzen?

von Dirk B. (dirkb2)


Lesenswert?

Josef schrieb:
> = -1.00368

Seien wir mal kühn und sagen -1.

Dann kommt bei acos(-1) pi raus.
Und als Endergebnis 12. Ist doch etwas anderes als 5,21131484.



Karl Heinz schrieb:
> PS. die math.lib hast du aber schon eingebunden?

Müßte nicht der Linker meckern, wenn die fehlt?

von CG (Gast)


Lesenswert?

@Karl Heinz
du meinst die math.h oder?

Mich wundert es das es in Excel so ohne weiteres berechnet werden 
kann.....hmmm

habe dann vorhin auch versucht dies zu machen:
1
if(x5<-1)
2
  x5 = x5 + 2;

aber geht auch nicht so wie ich es mir vorgestellt habe

von CG (Gast)


Lesenswert?

@Josef
ja ich programiere die Zahlen schon mit Punkt

von Karl H. (kbuchegg)


Lesenswert?

CG schrieb:
> @Karl Heinz
> du meinst die math.h oder?

nein, ich meine die Linkeroption -lm

> Mich wundert es das es in Excel so ohne weiteres berechnet werden
> kann.....hmmm

du hast gerade entdeckt, dass float mit seinen 5 bis 6 signifikanten 
Stellen auch nicht das gelbe vom Ei und die Lösung aller Probleme ist.

>
> habe dann vorhin auch versucht dies zu machen:
>
1
> if(x5<-1)
2
>   x5 = x5 + 2;
3
>
>
> aber geht auch nicht so wie ich es mir vorgestellt habe

wieso + 2 ?
1
  if( x5 < -1.0 )
2
    x5 = 1.0;
3
4
  if( x5 > 1.0 )
5
    x5 = 1.0;

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

CG schrieb:
> @Karl Heinz
> du meinst die math.h oder?

Nein, meint er nicht.

In der math.h stehen nur die Deklarationen, damit der Compiler die 
Funktionen kennt.
In der math.lib steht der (schon compilierte) Code dazu.

Wenn du die math.lib nutzen möchtest musst du sie manchmal extra mit 
dazu linken. Die Option ist meist -lm  (minus el em)

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

Die Cosinusfunktion hat einen Wertebereich von einschließlich -1 bis 
einschließlich 1. Entsprechen sieht der Defintionsbereich der 
Acosfunktion aus. Beträge größer 1 sind in der Tat nicht Bestandteil des 
Definitonsbereiches dieser Funktion. Mathestoff Klasse 7 in einer POS


Namaste

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

>
1
>   if( x5 < -1.0 )
2
>     x5 = 1.0;
3
>
Minus! Natürlich Minus Eins!
Blöder Tippfehler.
1
  if( x5 < -1.0 )
2
    x5 = -1.0;
3
4
  if( x5 > 1.0 )
5
    x5 = 1.0;

: Bearbeitet durch User
von CG (Gast)


Lesenswert?

so habe mein Problem gefunden

also ich habe in der h[i] den Wert -0,833 stehen jedoch muss ich diesen 
Wert noch durch 57,29578 dividieren damit mein Ergebnis richtig ist. In 
der ExcelTabelle dich ich gemacht hatte, hatte ich dies schon 
berücksichtig. Sorry Sorry Sorry

Also mit dem +2 wenn der Wert bei kleiner -1 ist habe ich mir gedacht, 
der ACOS setzt sich ja periodisch fort und somit müsste er dann bei 
einem Wert von kleiner als -1 ja auch, wenn ich eine zwei addiere 
auftreten.... wie gesagt das war nur so eine Überlegung....

Aber ich habe gelernt das die Funktion acos nicht mit Werten von kleiner 
-1 und größer +1 arbeiten kann, was natürlich auch stimmt.

Super ihr habt mir alle sehr weiter geholfen....

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.