Forum: Mikrocontroller und Digitale Elektronik Syntax unterscheidung gerade oder ungerade


von syntax(t)error (Gast)


Lesenswert?

Hi,
mal ganz schnell eine Frage zwischendurch - gibt es für c einen Syntax 
mit dem ich "recht einfach" unterscheiden kann ob ein unsigned char 
gerade oder ungerade ist!?

also sowas in der Art:
if(x=gerade){....}
else{

ich möchte nicht gross rumrechnen deswegen die frage nach einem 
feinfachen syntaxbefehl!

schankeDön!

von Elektro G. (e_g)


Lesenswert?

prüfe doch mit Modulo (%) ob ein Rest vorhanden ist!

von Sascha (Gast)


Lesenswert?

if(i % 2)
  // ungerade
else
  // gerade

Der Modulo-Operator gibt den Rest einer Ganzzahldivision aus.

Wird eine Zahl mit 2 dividiert und der Rest ist 0 -> gerade
Ist der Rest 1 -> ungerade

von Sascha (Gast)


Lesenswert?

ich meine durch 2 dividiert...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

#define GERADE(x) (((x) & 1) ? 0 : 1)

von Elektro G. (e_g)


Lesenswert?

ohne Garantie:

if (zahl%2 == 1)

von syntax(t)error (Gast)


Lesenswert?

oje, haja klar! - modulo, da war doch was! - hab ich voll verdrängt 
rolleyes

Danke!

von syntax(t)error (Gast)


Lesenswert?

ich glaube gandalf und sascha haben die gleiche Idee


@stefan - kannst du mir mal "Dein" define erläutern - verstehe das 
leider nicht :(

von Azrael (Gast)


Lesenswert?

Die version von Stefan B. ist wesentlich besser.
im prinzip musst du ja nur prüfen ob das LSB(niederwertigste Bit) 1 oder 
0 ist.
if( (x&1) == 0){
// gerade
}
else{
// ungerade
}
ist das gleiche nur als if-bedingung geschrieben

lg Azrael

von Der M. (steinadler)


Lesenswert?

Prüfe doch einfach das LSB.

von antworter (Gast)


Lesenswert?

Wenn es unsigned char, gibt das unterste Bit Aufschluß

// testen ob unterstes Bit gesetzt, wenn ja, ist term boolisch wahr
if (variable & 1)
{
   - ungerade
} else
{
   - gerade
}


Und das Zweierkomplement bei negativen, signed chars dürfte einem keinen 
Strich durch die Rechnung machen - das war doch: negiert plus eins - 
oder !?

von Florian (Gast)


Lesenswert?

neg = (~pos) + 1;

Bei negativen Werten geht das auch und übrigens nicht nur für unsigned 
char, sondern alle integer-typen, also char, short, long, long long usw. 
und eben auch signed.

Bei float-Typen (float, double) geht das so nicht.

von syntax(t)error (Gast)


Lesenswert?

okay alles klar - dürfte schneller als die modulo gehen!

Danke an Euch alle!!!

von Thomas F. (thomas-hn) Benutzerseite


Lesenswert?

> Und das Zweierkomplement bei negativen, signed chars dürfte einem keinen
> Strich durch die Rechnung machen - das war doch: negiert plus eins -
> oder !?

Beim Zweierkomplement eines signed char ist es doch so, dass wenn Bit 7 
(Nummerierung der Bits 0-7) gesetzt ist, dann hab ich den Wert -128. Die 
restlichen Bits (0-6) stellen eine positive Zahl dar, welche ich zu dem 
-128 dann addiere. Somit wäre die Zahl -127 (welche auch ungerade ist) 
als signed char 10000001. Somit dürfte es gehen, dass man nur das LSB 
prüft. Wenn es "1" ist --> ungerade, wenn es "0" ist --> gerade. Oder 
halt Modulo wie schon oben erwähnt :-)

Ich persönlich würde das LSB prüfen ;-)

Gruß,

Thomas

von Florian (Gast)


Lesenswert?

Ich habe übrigens auch schon häufig gesehen, dass der Compiler Moduli 
mit Zweierpotenzen in entsprechende Und-Verknüpfungen optimiert, aber 
das hängt mit Sicherheit von Compiler und Architektur ab.

von antworter (Gast)


Lesenswert?

@Thomas:

Sag' ich doch: Negiert plus 1

von A.K. (Gast)


Lesenswert?

@Florian: ... und davon, ob mit oder ohne Vorzeichen. Bei Datentypen mit 
Vorzeichen ist es deutlich komplizierter.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Jeder vernünftige Compiler wird aus "x % 2" "x & 1" machen, WENN es 
erlaubt ist. Diese Optimierung im C-Code vorwegzunehmen halte ich für 
keine gute Idee.

von syntax(t)error (Gast)


Lesenswert?

wieso ist eine Bitmaskierung nicht ratsam @Andreas?

Es ist m.M.n. mind. genau so verständlich wie die modulo.

Ich selbst sehen darin keinen Unterschied, wenn man einen "schlechten" 
Compiler hat der das nicht "wegoptimiert" dauert es deutlich länger - 
somit ist es für mich eine potentielle Bremsstelle im code, oder?

von Karl H. (kbuchegg)


Lesenswert?

syntax(t)error wrote:
> wieso ist eine Bitmaskierung nicht ratsam @Andreas?

Weil es die Methode verschleiert.
Die Absicht ist: feststellen ob eine Zahl gerade ist.
Die Methode ist: Wenn bei einer Division durch 2 ein
                 Rest von 0 übrig bleibt, dann ist die
                 Zahl gerade


  if( x % 2 == 0 )

drückt exakt die Methode aus.

>
> Es ist m.M.n. mind. genau so verständlich wie die modulo.

Nur wenn du über den Bitaufbau bescheid weist.

>
> Ich selbst sehen darin keinen Unterschied, wenn man einen "schlechten"
> Compiler hat der das nicht "wegoptimiert" dauert es deutlich länger -
> somit ist es für mich eine potentielle Bremsstelle im code, oder?

Wenn du tatsächlich einen Compiler findest, der diese Optimierung
nicht macht, dann schmeiss den Compiler weg und besorg dir
einen vernünftigen Compiler den kein Studienanfänger geschrieben
hat.

Klarheit im Programm geht immer vor Performance
(mit Ausnahmen natürlich)

von A.K. (Gast)


Lesenswert?

Dummerweise ist -3 % 2 aber nicht 1, sondern -1.

von Karl H. (kbuchegg)


Lesenswert?

A.K. wrote:
> Dummerweise ist -3 % 2 aber nicht 1, sondern -1.

Und?
-1 ist nicht 0 und daher ist -3 auch nicht gerade.

Oder willst du auf etwas anderes hinaus?


(Glück gehabt: noch mal nach oben gescrollt ergibt, dass
von einem unsigned char die Rede ist. -3 ist daher aussen vor)


von Florian (Gast)


Lesenswert?

<sarkasmus>

Dann nimmt man eben die unverschleierte Konstruktion

if ( ( ( x % 2 ) == 1 ) || ( ( x % 2 ) == -1 ) )

anstatt

if ( x & 1 )

</sarkasmus>

von antworter (Gast)


Lesenswert?

>Weil es die Methode verschleiert

...wofür es Kommentare gibt

von A.K. (Gast)


Lesenswert?

> Oder willst du auf etwas anderes hinaus?

Ich will darauf hinaus, das kein Compiler bei Typen mit Vorzeichen (x % 
2) einfach zu (x & 1) optimieren darf. Dividieren muss er zwar nicht, 
aber bissel komplizierter ist es dennoch. Bei der Division sieht das 
beispielsweise für x / (2**n) so aus:
1
if (x < 0)
2
    x += (2**N)-1;
3
return x >> N;

  

von antworter (Gast)


Lesenswert?

P.S.: Wer das 2er Komplement nicht kennt, ist meiner Quelltexte nicht 
würdig ;-)

von Florian (Gast)


Lesenswert?

@A.K.:
Auf vielen Architekturen gibt es die Unterscheidung zwischen logical 
shift right und artihmetic shift right. Bei letzterem wird dann von 
links nicht mit Nullen, sondern dem ursprünglichen höchsten Bit gefüllt. 
Dann bleibt das ganze wieder konsistent.

Der C-Compiler allerdings macht immer ein logical shift right, so dass 
Dein Konstrukt notwendig wäre, allerdings ist es vermutlich besser 
tatsächlich so was wie

y = x / ( 1 << N )

zu schreiben, da der Compiler das vermutlich zu

asr x, N

vereinfachen würde.

von A.K. (Gast)


Lesenswert?

> Bei letzterem wird dann von links nicht mit Nullen,
> sondern dem ursprünglichen höchsten Bit gefüllt.
> Dann bleibt das ganze wieder konsistent.

Nein. Die C Division rundet gegen Null, der arithmetische Shift gegen 
Minus Unendlich.

von Peter D. (peda)


Lesenswert?

Florian wrote:

> Der C-Compiler allerdings macht immer ein logical shift right

Nein, er schiebt immer richtig (typabhängig):

Bei unsigned schiebt er ne 0 rein.
Bei signed schiebt er das höchstwertige Bit (Vorzeichenbit) weiter.


Peter

von A.K. (Gast)


Lesenswert?

> Glück gehabt: noch mal nach oben gescrollt ergibt, dass
> von einem unsigned char die Rede ist. -3 ist daher aussen vor

Pech gehabt. Die integer promotion von C bringt es mit sich, dass solche 
Ausdrücke als "int" gerechnet werden.

Wenn der Compiler das erst zu 16 oder 32 Bits erweitert, dann geht ihm 
auf dem Weg allzu leicht die Information verloren, dass negative Werte 
nicht vorkommen können.

Und genau das passiert mindestens bei den PC-Compilern von Microsoft und 
Walter Bright (Digital Mars).

von Karl H. (kbuchegg)


Lesenswert?

A.K. wrote:
>> Glück gehabt: noch mal nach oben gescrollt ergibt, dass
>> von einem unsigned char die Rede ist. -3 ist daher aussen vor
>
> Pech gehabt. Die integer promotion von C bringt es mit sich, dass solche
> Ausdrücke als "int" gerechnet werden.

Grummel, grummel.
Das Glück ist ein Vogerl  (alte österr. Volksweisheit)

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.