Forum: Mikrocontroller und Digitale Elektronik Multiplikation führt zum falschen Ergebnis! Warum?


von Daniel (Gast)


Lesenswert?

Hallo,

ich arbeite gerade in meiner Diplomarbeit an einem Programmiergerät für 
einen Winkelsensor. Ich benutze dabei einen AVR mega8. Bei der 
Berechnung einiger Werte habe ich unter anderem folgendes
1
unsigned long int a = 0;    // maximal 2^32 - 1 = 4.294.967.295
2
  unsigned long int b = 0;
3
  unsigned long int c = 0;
4
5
  calc_ang_rng_mult = ((1000 * (unsigned long int)ang_rng_mult) / 16384);    // = 524.287.000 / 16.384 = 31.999,...
6
7
  a = (((unsigned long int)(clamp_hi - clamp_lo) * 100000) / 8192);      // = 460.700.000 / 8.192 = 56.237,...
8
  b = ((180 * 10000000) / calc_ang_rng_mult);                  // = 1.800.000.000 / 31.999 = 56251,...
9
  c = ((unsigned int)a * (unsigned int)b);                  // = 56.251 * 31.999 = 1.799.975.749
10
  calc_ang_rng = (c / 100000);

Die dezimalen Maximalwerte habe ich jeweils als Kommentar in den Code 
eingefügt. Die Variablen calc_ang_rng_mult, a und b werden richtig 
berechnet. Die Werte stimmen mit dem überein, was als Kommentar in der 
jeweiligen Zeile steht. Variable c erhält jedoch nicht den Wert 
1.799.975.749 sondern nur 30.303. Warum ist das so? 1.799.975.749 müsste 
ich doch in einer unsigned long int Variable darstellen können.

Für Hinweise oder Erklärungen wäre ich sehr dankbar! Wie das immer so 
ist bei Diplomarbeiten: Die Zeit rennt...

Grüße,
Daniel

von Ralf (Gast)


Lesenswert?

> unsigned long int a = 0;
??? Ich dachte, es gibt entweder LONG oder INT, aber nicht beides 
zusammen?

> c = ((unsigned int)a * (unsigned int)b);
Wenn du auf explizit auf INT castest, kommt dann nicht auch ein INT 
raus? Muss mal mein C-Buch rausholen, hab's grad nicht hier.

Ralf

von (prx) A. K. (prx)


Lesenswert?

Ralf wrote:

> ??? Ich dachte, es gibt entweder LONG oder INT, aber nicht beides
> zusammen?

Offiziell heisst das "long int" und "short int", aber man darf das "int" 
weglassen.

von (prx) A. K. (prx)


Lesenswert?

Ich habe mir den Kram jetzt nicht im Detail angesehen, es gab aber eine 
WinAVR Version, die mit "long" Multiplikation auf Kriegsfuss stand. 
4.3.0 von April/Mai oder so. Auch manche Version aus debian und Ubuntu.

von Daniel (Gast)


Lesenswert?

Hallo!

Danke für die schnelle Antwort. Ja, die Typumwandlung (unsigned int)a 
bzw. b habe ich nachträglich als Versuch mal mit dort reingebracht. Wenn 
ich es weglasse, dann steht in c der Wert 3.163.387.487 - das ist 
immerhin was anderes, aber der µC hat sich immer noch verrechnet :-)

Grüße,
Daniel

von Daniel (Gast)


Lesenswert?

Hallo,

ich habe die letzte offizielle WinAVR-Version, Release 20081205 
installiert.

Den Vorschlag von Michael habe ich ausprobiert:
c = ((unsigned long int)a * (unsigned int)b);

Das Ergebnis ist wieder 3.163.387.487...

Grüße,
Daniel

PS: Wahnsinn, wie schnell hier die Antworten kommen! Vielen Dank!

von Route_66 (Gast)


Lesenswert?

Ist ja auch richtig! Schau mal in Deine Kommentarzeilen  wo a= und b= 
vorne stehen (ich sehe da keine 31.999)!?

von Michael K. (mmike)


Lesenswert?

Versuch mal die Datentypen aus der <inttypes.h> in Deinem Fall also 
uint32_t.
Und lass die Typecasts mal bei der Multiplikation weg ...

also:
1
uint32_t a = 0;    // maximal 2^32 - 1 = 4.294.967.295
2
uint32_t b = 0;
3
uint32_t c = 0;
4
5
calc_ang_rng_mult = ((1000 * (uint32_t)ang_rng_mult) / 16384);
6
a = (((uint32_t)(clamp_hi - clamp_lo) * 100000) / 8192);
7
b = ((180 * 10000000) / calc_ang_rng_mult);
8
c = (a * b);
9
calc_ang_rng = (c / 100000);

Grüße,
Michael

von Route_66 (Gast)


Lesenswert?

jedenfalls nicht als Ergebnis (vielleicht besser 56.237)

von Artem G. (jorjo)


Lesenswert?

Hallo,

Versuch mal vielleicht "c=a*b;" zu schreiben;
weil "c" vom gleichen Typ wie a und b ist

Mfg
Artem

von Daniel (Gast)


Lesenswert?

Route_66 hat völlig recht! Ich bin ein Trottel und sehe den Wald vor 
lauter Bäumen nicht mehr... Das Ergebnis stimmt ja auch - die 
Kommentarzeile ist falsch!

Ich danke auch trotzdem! Wir ist einiges klar geworden bezüglich den 
evtl. notwendigen Typumwandlungen bei Multiplikation. War also nicht 
völlig umsonst!

Dankeschön,
Daniel

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.