Hallo, ich möchte in meinem Programm eine Berechnung ausführen (AVRGCC 20100110, Atmega16) und zwar: x = ( l*m*100 ) / ( d*a ) mit l=0...500; m=0...1023; d=1...250 a=1...1023 Wie kann ich diese Berechnung am Besten implementieren? Hab schon diverse Varianten ausprobiert und bekomme im AVR Simulator und auf der Zielhardware immer wieder falsche Ergebinsse. z.B.: für: temp=(uint16_t)((d*a)/1024); liefert der Simulator als Ergebnis mit d=250 und a=800 temp=3 obwohl es 195 seien sollten. Wie bekomme man den Überlauf der Zahlen (d*a) wärend der Berechung in den Griff? Kann das der Compiler von sich aus? Danke für die Hilfe.
Der Compiler achtet darauf nicht. Du musst bei ALLEN Zwischenschritten selbst prüfen, ob ein Überlauf auftreten kann, und dann die Operanden auf den passenden Typ casten. In deinem Fall also auf 32 Bit.
Das einfachste ist, alle verwendeten Variablen als unsigned long zu definieren.
1 | unsigned long x, l, m, d, a; |
2 | |
3 | l = 100; |
4 | m = 10; |
5 | d = 50; |
6 | a = 10; |
7 | |
8 | x = ( l*m*100 ) / ( d*a ); |
Grüße, Peter
Hallo vielen Dank euch Beiden. Hab jetzt in der Berechnung bei den Überläufen auf 32bit Variable gecastet und jetzt funktioniert die Rechnung. Auf die 2. Variante hätte ich auch selber kommen können.... Schönen Abend noch.
Hi, ja ja die bösen Integer ;-) aber mal im ernst, UINT16 => 2^16 => 0..65535 du musst bei deiner Berechnung sicherstellen das der Datenbereich nicht überlaufen wird. Dabei verlierst du allerdings an Genauigkeit. (einen Tot muss man ja sterben ;-) ) Genrell musst du versuchen durch geschicktes skalieren des Dividenden und zerlegen des Divisors innerhalb deiner gegebenen grenzen zu bleibe.
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.