Multiplikation führt zum falschen Ergebnis! Warum?

Gast #1175297
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
Gast #1175313
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
Gast #1175323
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
Gast #1175329
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!
#1175337
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
Gast #1175344
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren