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!
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
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
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 !?
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.
> 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
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.
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.
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?
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)
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)
> 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:
@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.
> 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.
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
> 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).
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)