PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Lösen von Überlauf



XBert
28.08.2010, 15:17
Hi,
Ich habe folgendes Problem und weiß nicht genau wie man es möglichst effizient lösen kann.
Es gibt eine Funktion die ein int16_t verlangt. Ich rufe sie folgendermaßen auf:
foo(((int32_t)x<<15)/y);
das Problem tritt auf, wenn x==y da dann 32768 übergeben wird was natürlich zu einem falschem Ergebnis führt.
Meine Lösungsversuche sind die:
foo(((int32_t)x*32767)/y);
foo(((int32_t)x<<15)/y-1);
Allerdings bin ich mit beiden Varianten nicht ganz glücklich da sie bei allen anderen Werten zu einem (kleinem) Fehler führen.
Hat jemand eine schlaue Idee dazu?

Und meine 2te Frage ist was passiert bei einer Division durch 0 auf einem AVR.
Mathematisch gesehen ist das ja nicht definiert, aber was passiert im µC?


LG

PicNick
28.08.2010, 15:48
1) müsste das nicht heissen:
foo ( (int16_t)( (int32_t)(x << 15) / (int32_t)y ) )

2)
ich glaub, das Ergebnis ist "unpredictable". Da es ja keine DIV instruction für den µC gibt, ist der Compiler zuständig, die Division zu generieren UND so einen Check zu machen.
Am besten den AVR mal in sowas hineinhetzen und mal gucken, ob es wo zu rauchen beginnt *g*

XBert
28.08.2010, 16:02
ad 1) nicht unbedingt, da bei mir y ohnehin 32 bit lang ist, und das Gesamtergebnis vor dem Übergeben an die Funktion automatisch gecastet wird.

ad 2) werd ich probieren

P.S.: Gratuliere zum 7000endsten Beitrag ;)

PicNick
28.08.2010, 17:56
ahja, das geht dahin, thx *g*

Den Fall x==y könntest du vorher abfragen.
Aber was kannst du in diesem Fall der Funktion denn (gültiges) übergeben ?

XBert
29.08.2010, 14:41
Ach ja, das hab ich vergessen zu erwähnen. Die Funktion liefert zu jedem Wert im Intervall -32768 bis 32767 einen Wert (die Funktion ist quasi stetig). Daher möchte ich statt 32768 einfach 32767 übergeben.
Allerdings ist eine if-Schleife mMn das Umständlichste.
im Moment verwende ich die Multplikation mit 32767 da der Fehler dann insgesamt geringer ist als wenn ich überall 1 abziehe.

Felix G
29.08.2010, 14:59
Falls x != y nicht sichergestellt werden kann, wäre ein if allerdings die sauberste Lösung...


int16_t tmp = (x != y) ? (((int32_t)x << 15) / y) : 32767;

foo(tmp)

XBert
29.08.2010, 15:37
So Leute, das Ganze hat sich wohl aufgelöst.
Ich habe mir die Funktion mal genauer angesehen und bemerkt das mein (x<<15) eigentlich falsch ist da, ohnehin mit 32767 multipliziert werden müsste um 100% richtig zu sein.

LG