Forum: Compiler & IDEs Differenz im Integer-Zahlenraum


von Walter T. (nicolas)


Lesenswert?

Guten Morgen,
es ist Sonntagmorgen und meine Liebste schläft quasi auf meinem C-Buch. 
Wenn ich zwei Integer-Zahlen, meinetwegen int8_t a,b , habe, haben diese 
in ihrem zyklischen Zahlenraum mehrere Abstände, nämlichb z.B.:

diff1 = b-a;
diff2 = b-256*a;
usw.

Das wird immer dann interessant, wenn eine Variable überträgt, bei mir 
konkret im folgenden Fall:
1
int8_t this,last,delta;
2
this = zaehleraehnliche_funktion();
3
4
while(1) {
5
  last = this;
6
  this = zaehleraehnliche_funktion();
7
  delta = this-last;
8
9
  ...
10
}
Im Moment des Übertrags steht in this=-128 und in last = 127, was vom 
normalen Differenzoperator völlig richtig als -255 interpretiert wird - 
aber der Abstand, den ich wirklich suche ist ja 1. Bei der umgekehrten 
Richtung entsteht das gleiche Problem.
Wie geht es am effizientesten, den kürzesten gerichteten Abstand im 
Zahlenraum auf einem AVR zu berechnen?

Viele Grüße
Nicolas

von Yalu X. (yalu) (Moderator)


Lesenswert?

Mach die Variablen this, last und delta alle vom Typ uint8_t. Dann 
bekommst du immer eine positive Differenz heraus, auch beim Überlauf. 
Außerdem ist das Ergebnis von Additionen und Subtraktionen bei 
Überläufen im C-Standard nur für Unsigned-, nicht aber für Signed-Werte 
spezifiziert.

von Walter T. (nicolas)


Lesenswert?

Guten Morgen Yalu,
stimmt, die Undefiniertheit beim Überlauf habe ich schon wieder 
verdrängt, weils beim AVR-GCC immer funktioniert.

diff muß signed bleiben: Ich brauche das Vorzeichen der Differenz - 
zaehleraehnliche_funktion() zählt vorwärts und rückwärts. Und das 
Problem des Abstandes bleibt dabei gleich.

Vermutlich komme ich um den Vergleich des Betrags von "delta" mit 127 
nicht herum. Aber ich bin trotzdem noch gespannt.

von Walter T. (nicolas)


Lesenswert?

OK, das war meine Dummheit am Sonntagmorgen: Das Problem tritt gar nicht 
auf, wenn man es richtig macht. In meinem ursprünglichen Programm habe 
ich dieses Konstrukt verwendet:
1
int16_t counter = 0;
2
int8_t this,last,delta;
3
this = zaehleraehnliche_funktion();
4
5
while(1) {
6
  last = this;
7
  this = zaehleraehnliche_funktion();
8
  counter += this-last;
9
10
  ...
11
}
Damit wird der "this-last" in einen int16 gecastet und damit kann der 
große Übertrag erst auftauchen. Bei
1
int18_t counter = 0;
2
int8_t this,last,delta;
3
this = zaehleraehnliche_funktion();
4
5
while(1) {
6
  last = this;
7
  this = zaehleraehnliche_funktion();
8
  delta = this-last
9
  counter += delta;
10
11
  ...
12
}
tritt das Problem gar nicht auf.

Danke für die Diskussion! Ansonsten wäre mir die 
signed-Überlauf-Problematik nicht bewußt gewesen.

von Dr. Sommer (Gast)


Lesenswert?

Kleiner Hinweis: Variablen bitte nicht 'this' nennen, dann funktioniert 
der Code auch noch wenn er irgendwann eventuell einmal als C++ verwendet 
wird...

von Nicolas S. (Gast)


Lesenswert?

Keine Sorge, so kurze Namen gibt es nur, wenn Quelltexte für Forenfragen 
gekürzt werden.

von Dr. Sommer (Gast)


Lesenswert?

Nicolas S. schrieb:
> Keine Sorge, so kurze Namen gibt es nur, ...
Na die Länge ist nicht das Problem, mehr die Tatsache dass "this" ein 
reserviertes Schlüsselwort in C++ (und anderen Sprachen...) ist ;-)

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Und selbst in Sprachen, in denen "this" kein reserviertes Schlüsselwort 
ist, gibt es trotzdem die Konvention, es ausschließlich für eine 
Referenz bzw. einen Zeiger auf das aktuelle Objekt zu verwenden.

Eine ähnliche Konvention gibt es für "self", z.B. in Python:

http://stackoverflow.com/questions/1079983/why-do-pythonistas-call-the-current-reference-self-and-not-this

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.