2009-09-22 13 views
6
for (unsigned int i = 1; i <= 100; i++) { 
    if (i & 0x00000001) { 
     std::cout << i<<","; 
    } 
} 

warum (und wie): if(i & 0x00000001) die ungerade Zahl herausfinden?warum funktioniert das? (Suche ungerade Zahl in C++)

+0

Normalerweise ist es geschrieben 'i & 0x00000001', mit einem Raum zwischen bitweise und (' & ') und den Operanden. – xtofl

+15

Sie wissen, i & 1 macht den Trick auch. – ypnos

+0

macht es einen Unterschied? ob es einen Raum gibt oder nicht? (nur fragen) – Tom

Antwort

22

0x00000001 ist 1 in binär, obwohl es in hexadezimal (Basis 16) Notation geschrieben. Das ist der 0x Teil.

& ist der bitweise AND-Operator, mit dem binäre Ziffern (Bit) manipuliert werden.

i & 1 konvertiert alle Binärziffern von i auf null, mit Ausnahme der letzten.

Es ist einfach, die resultierende 1-Bit-Zahl in einen booleschen zu konvertieren, zur Auswertung durch die if-Anweisung.

Die folgende Tabelle zeigt die letzten 16 Binärziffern von i und was mit ihnen passiert.

i: i in binary:  i & 1 in binary: convert to boolean 
---- ------------------- ------------------- --------------------- 
1 0000000000000001 0000000000000001 true 
2 0000000000000010 0000000000000000 false 
3 0000000000000011 0000000000000001 true 
4 0000000000000100 0000000000000000 false 
5 0000000000000101 0000000000000001 true 
6 0000000000000110 0000000000000000 false 
7 0000000000000111 0000000000000001 true 
8 0000000000001000 0000000000000000 false 
... ...     ...     ... 
99 0000000001100011 0000000000000001 true 
100 0000000001100100 0000000000000000 false 
+0

funktioniert das nur für Integer, oder funktioniert das auch für Floats? Es hat mich zum Nachdenken gebracht, weil Floats anders im Speicher gespeichert sind, aber mit dem Modulo-Operator werden sie in Ints umgewandelt, mit bitweisem 'und' gibt es keinen Cast. – knittl

+0

Sie können keine bitweisen Operatoren auf Fließkommazahlen anwenden, da sie in einem plattformspezifischen Format dargestellt werden und das am häufigsten verwendete Format eignet sich nicht gut für bitweise Operationen. – coppro

+0

können Sie nicht? Also wird dies zu einem Compilerfehler führen? oder nur in unspezifiziertem Verhalten? – knittl

21

Es verwendet einen bitweisen "und" Operator, um alle bis auf das letzte Bit zu maskieren. Wenn das letzte Bit eine 1 ist, ist die Zahl ungerade. Ist das genug Erklärung?

+4

+1, ich persönlich würde auch gerne eine Erklärung für die Verwendung der sesquipedalischen Notation anstelle von '1' hören ;-) –

+0

Das war gut gesagt. –

+6

(zum ursprünglichen Poster) Wenn Sie diese Antwort nicht verstehen, die richtig ist, versuchen Sie, 5 gerade Zahlen und 5 ungerade Zahlen zu binär zu ändern. Beobachte, was auf dem letzten Bit passiert und wie sich das auf die transformierte Zahl bezieht. (Genauer gesagt, was passiert, wenn die Zahl gerade ist und wenn die Zahl ungerade ist). Lesen Sie auf bitweise UND – Malaxeur

13

Wenn wir uns Zahlen in der Basis 10 ansehen, ist es leicht zu sagen, ob eine Zahl durch 10 teilbar ist: Es hat eine 0 an der letzten Position. Der Code oben sieht auch die Ziffer in der letzten Position, aber in der Basis 2. Wenn es nicht Null ist, ist die Zahl nicht durch 2 teilbar.

+0

+1 für nicht zu empfehlen, zu versuchen und nach ein paar Zahlen zu überprüfen. –

10

Es maskiert das letzte Bit. Wenn Sie sich jede Stelle in der Binärdarstellung einer Zahl ansehen (..., 256, 128, 64, 32, 16, 8, 4, 2 und 1), werden Sie feststellen, dass nur die Stelle des einen ungerade ist. Alle anderen Orte haben einen geraden Wert, egal ob die Bits gesetzt oder gelöscht sind (Null ist gerade). Und das Hinzufügen gerader Zahlen ergibt immer eine gerade Zahl. Nur der Ort des letzten bestimmt die Parität der Nummer. Der i & &0x00000001 Teil isoliert nur diesen letzten Platz.

3

Sie machen einen bitweisen Vergleich. Wenn if bit0 AND bit0 beide 1 sind, dann ist die Antwort bit0 = 1.

Da & 0x00000001 1 ist, sind alle Zahlen mit diesem Bit ungerade.

0x00000001 = 1 
0x00000010 = 2 
0x00000011 = 3 
etc. 

Also, wenn Sie eine bitweise tun UND

00000001 AND 
00000001 = 
00000001 (same as true) 

00000010 AND 
00000001 = 
00000000 (same as false) 

00000011 AND 
00000001 = 
00000001 (same as true) 

etc 
2

Ungerade Zahlen sind alle Zahlen der Form (2 * n + 1) wobei n eine ganze Zahl ist (-2, -1,0,1 ....). Um also eine ungerade Zahl zu finden, müssen Sie sehen, ob die Zahl, mit der Sie arbeiten, die +1 hat. Wenn sie als vorzeichenlose ganze Zahl gespeichert wird, kann eine Zahl als die Summe der Potenzen von 2: 2^0 + 2^1 + 2^2 + 2^4 usw. ausgedrückt werden. Die binäre Version der vorzeichenlosen ganzen Zahl sieht wie eine Wahrheitskarte aus Für jeden Ort gibt es eine "1" in der Binärzahl, addiere diese Zweierpotenz zu der Zahl. Wenn Sie also in der binären Darstellung der Ganzzahl ohne Vorzeichen an der Stelle ganz rechts beginnen und sich nach links bewegen, steht jede Stelle für eine Potenz von Zwei. Wenn die Ziffer 1 ist, addieren Sie diese Zweierpotenz zur laufenden Summe und zum Ende der Binärzahl.

So:

Ganz rechts:: 2^1 + 2^2 + 2^3 + 2^7: Ganz links = 141

Die 10001110b kann durch Summieren der Potenzen von zwei in eine ganze Zahl umgewandelt werden, Trick ist, dass die Ziffer ganz rechts 2^0 darstellt. Dies ist immer 1. Alle anderen Ziffern stehen für gerade Zahlen. Also, in Bezug auf ungerade Zahlen müssen Sie die "+1" finden. Das entspricht der Ziffer ganz rechts. Alle anderen Ziffern stellen Zahlen der Form '2 * n' dar. Um festzustellen, ob eine Zahl dieses Formats (vorzeichenlose ganze Zahl) ungerade ist, müssen Sie nur sehen, ob das rechte Bit "1" ist.

Die für die Ganzzahl ohne Vorzeichen ausgeführte Operation ist eine logische UND-Operation. Alles AND'd mit 0 ist 0, und 1 UNDd mit 1 ist 1. Die Operation bewirkt also, dass alle Binärziffern in der vorzeichenlosen Integer-Darstellung 0 sind, mit Ausnahme der Binärziffer, die 2^0 darstellt (was 1 ist). Also wird die vorzeichenlose Integer-Binärdarstellung auf 0x00000001 reduziert, wenn sie ungerade ist, und auf 0x00000000, wenn sie gerade ist.

Hinweis: Wenn ich 0x00000000 schreibe, bedeutet "0x", dass es hexadezimal ist. Jede '0' repräsentiert vier Bits. So ist 0x00 hexadezimal für 00000000b binär schrieben, die sich daraus ergebenden möglichen unsigned integer binären Darstellungen nach den unsigned integer verUNDen sind:

00000000000000000000000000000000b == 0 und 00000000000000000000000000000001b == 1

2

Bevor ich sagen Im Folgenden werde ich zuerst sagen, dass ich den Bit-Test ziemlich oft verwende, um zu bestimmen, ob ein int gerade oder ungerade ist.

Aber genau genommen sollten Sie (i % 2) oder ((i % 2) != 0) verwenden, um festzustellen, ob i ungerade ist. Dies funktioniert unabhängig von der Darstellung negativer Zahlen, während auf einer eigenen Komplement-Maschine (-3 & 0x01) Null zurückgibt (ein falsches Ergebnis), obwohl es eindeutig ungerade ist.

Ich erkenne, dass Machiens, die etwas anderes als Zweierkomplement verwenden, um eine negative Zahl darzustellen, sehr, sehr selten heutzutage sind, aber es ist auch wahr, dass Compiler heutzutage (i % 2) auf jeden Fall kompilieren werden. Und denken Sie daran, dass ich normalerweise meinen eigenen Rat hier nicht befolge, also könnte das ein Hinweis auf den wahren Wert dieses Vorschlags sein.

0

Die bitweise AND-Operator folgt dieser Wahrheitstabelle für jedes Bit:
0 = 0
1 = 0
0 = 0
1 = 1

Da Computer arbeiten mit Zahlen in der Basis 2 und jedes Bit stellt eine Zweierpotenz dar (1,2,4,8,16 ..),
das niedrigstwertige Bit stellt die einzige ungerade Zahl dar, unabhängig davon, wie groß oder klein der Wert ist, und unabhängig davon, ob es signiert oder nicht signiert ist. Da das resultierende Bit nur gesetzt wird, wenn beide Operanden dieses Bit gesetzt haben, ist das Ergebnis genau dann wahr, wenn die Zahl ungerade ist.

Beispiel: 0b1110101 =
(1 * 2^0) + (1 * 2^1) + (0 * 2^2) + (1 * 2^3) +
(0 * 2^4) + (1 * 2^5) + (1 * 2^6) + (1 * 2^7) =
+ 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
Ohne das niedrigstwertige Bit wäre der Wert 234 und daher eine gerade Zahl.

0

Für Beispiel, wie wir machen eine binäre Äquivalent

0 0 0 0 = 0

0 0 0 1 = 1

0 0 1 0 = 2

0 0 1 1 = 3

So können Sie für jede ungerade nicht sehen. LSB ist immer gesetzt, Samen Sie überprüfen :)

Ich hoffe, meine Antwort ist klar