Forum: Mikrocontroller und Digitale Elektronik negatives Ergebnis in unsigned


von qwertz (Gast)


Lesenswert?

Hallo,

ich steh grad voll auf dem Schlauch.

Folgendes Problem:

uint8_t var1 = 7;
uint8_t var2 = 5;
uint8_t res = var2 - var1;

Was steht nun in res?
Theoretisch -2. Die Variable ist doch aber unsigned?

Danke.

von Mike (Gast)


Lesenswert?

> Theoretisch -2. Die Variable ist doch aber unsigned?
Negative Zahlen werden i.a. als Zweierkomplement dargestellt. In res 
wird dann also 254 stehen.

von A. (Gast)


Lesenswert?

Das ergibt einen Überlauf. 254 ist das Ergebnis. Und jetzt kommt der 
Zaubertrick:
1
uint8_t var1 = 7;
2
uint8_t var2 = 5;
3
uint8_t res = var2 - var1;
4
5
if(res >= 0x80)
6
  printf("Das Ergebnis ist: -%u", (res ^ 0xFF) + 1); 
7
else
8
  printf("Das Ergebnis ist: %u", res );

oder
1
uint8_t var1 = 7;
2
uint8_t var2 = 5;
3
uint8_t res = var2 - var1;
4
5
printf("Das Ergebnis ist: %i", (char)res);

von Volle (Gast)


Lesenswert?

Es gibt auch Mikrocontroller die unterstützen gesättigte Arithmetik. 
Allerdings muss man sich daraus erst ein C-Funktion bauen, da es die 
Compiler i.d.R. nicht unterstützen.

von qwertz (Gast)


Lesenswert?

Ich danke euch!

von Axel S. (a-za-z0-9)


Lesenswert?

A. schrieb:
> ... jetzt kommt der Zaubertrick:
>
>
1
> uint8_t var1 = 7;
2
> uint8_t var2 = 5;
3
> uint8_t res = var2 - var1;
4
> 
5
> if(res >= 0x80)
6
>   printf("Das Ergebnis ist: -%u", (res ^ 0xFF) + 1);
7
> else
8
>   printf("Das Ergebnis ist: %u", res );
9
>

Das ist ein ausgesprochen blöder Trick. Im folgenden Code findet kein 
Überlauf statt, aber dein "Trick" glaubt das trotzdem und liefert 
folglich ein falsches Ergebnis.
1
uint8_t var1 = 7;
2
uint8_t var2 = 240;
3
uint8_t res = var2 - var1;
4
...

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Axel S. schrieb:
> uint8_t var2 = 240;

Ich verstehe Eure Tricks nicht - Uint_irgendwas ist doch Unsigned - also 
vorzeichenlos und somit gibt es dort keine negativen Zahlen.

Bei vorzeichenbehafteten Zahlen ist das höchste Bit das Vorzeichen, 
gesetzt ist die Zahl negativ und im 2er-Komplement.
Wobei dann eine signed 8bit 240 negativ ist, eine signed 16bit 240 aber 
noch lange nicht.

MfG

von A. (Gast)


Lesenswert?

Axel S. schrieb:
> A. schrieb:
> Das ist ein ausgesprochen blöder Trick. Im folgenden Code findet kein
> Überlauf statt, aber dein "Trick" glaubt das trotzdem und liefert
> folglich ein falsches Ergebnis.
> uint8_t var1 = 7;
> uint8_t var2 = 240;
> uint8_t res = var2 - var1;
> ...

240 ist auch eine negative Zahl (-16). Aber das muss der TO erst noch 
lernen.

von jz23 (Gast)


Lesenswert?

A. schrieb:
> 240 ist auch eine negative Zahl (-16). Aber das muss der TO erst noch
> lernen.

Nein, du musst wohl lernen, dass die Variable "uint" heißt. Da ist 240 
240 und nichts anderes.

von (prx) A. K. (prx)


Lesenswert?

A. schrieb:
> Das ergibt einen Überlauf.

Die Subtraktion erfolgt mit beiden Operanden als "int" und da läuft 
nichts über.

von Axel S. (a-za-z0-9)


Lesenswert?

Patrick J. schrieb:

> Ich verstehe Eure Tricks nicht

Bitte dichte mir nicht irgendwelche Tricks an.

> Uint_irgendwas ist doch Unsigned - also
> vorzeichenlos und somit gibt es dort keine negativen Zahlen.

Ja. Eben.

> Bei vorzeichenbehafteten Zahlen ist das höchste Bit das Vorzeichen,
> gesetzt ist die Zahl negativ und im 2er-Komplement.

Und bei unsigned ist das höchste Bit schlicht das höchste Bit. Es hat 
keine spezielle Bedeutung. Insbesondere taugt es nicht dazu, einen 
Überlauf bei einer vorherigen Rechenoperation anzuzeigen. Genau deswegen 
ist der "Trick" ja so dämlich.

> Wobei dann eine signed 8bit 240 negativ ist, eine signed 16bit 240 aber
> noch lange nicht.

8 Bit signed kann nicht 240 sein. Der Wertebereich geht von -128 bis 
+127.

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.