www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Syntax unterscheidung gerade oder ungerade


Autor: syntax(t)error (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Elektro Gandalf (e_g)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
prüfe doch mit Modulo (%) ob ein Rest vorhanden ist!

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich meine durch 2 dividiert...

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define GERADE(x) (((x) & 1) ? 0 : 1)

Autor: Elektro Gandalf (e_g)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ohne Garantie:

if (zahl%2 == 1)

Autor: syntax(t)error (Gast)
Datum:

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

Danke!

Autor: syntax(t)error (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich glaube gandalf und sascha haben die gleiche Idee


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

Autor: Azrael (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Micha (steinadler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Prüfe doch einfach das LSB.

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 !?

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: syntax(t)error (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
okay alles klar - dürfte schneller als die modulo gehen!

Danke an Euch alle!!!

Autor: Thomas Finke (thomas-hn) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Thomas:

Sag' ich doch: Negiert plus 1

Autor: A.K. (Gast)
Datum:

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

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: syntax(t)error (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: A.K. (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)


Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
<sarkasmus>

Dann nimmt man eben die unverschleierte Konstruktion

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

anstatt

if ( x & 1 )

</sarkasmus>

Autor: antworter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Weil es die Methode verschleiert

...wofür es Kommentare gibt

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
if (x < 0)
    x += (2**N)-1;
return x >> N;

  

Autor: antworter (Gast)
Datum:

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

Autor: Florian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.