|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Terep Mini JLI'ler
Anmeldedatum: 02.05.2008 Beiträge: 18 Wohnort: Hannover Medaillen: Keine
|
Verfasst am: 17.05.2008, 09:37 Titel: Bit-Operatoren |
|
|
Hi Leute
Erst dachte ich, dass ich die Verwendung von Bit-Operatoren verstehe.
Doch dem ist nicht so.
Ich habe hier einen funktionierenden Buchquellcode, den ich nicht verstehe.
In diesem Programm wird jede eingegebene ganze Zahl binär ausgegeben.
Code: |
#include<iostream>
using namespace std;
int main ()
{
cout << "\nZahl als binaere Zahl ausgeben\n";
cout << "\nGebe eine ganze Zahl ein: ";
int zahl;
cin >> zahl;
int anzahlDerBytes = 2;
int anzahlDerBits = 8 * anzahlDerBytes;
for (int k = anzahlDerBits - 1; k >= 0; --k)
{
if (zahl & (1 << k)) // & = bitweises und
{
cout << "1";
}
else
{
cout << "0";
}
}
cout << endl;
}
|
Ich kapiere aber nicht die if-Bedingung
if (zahl & (1 << k))
wird Zahl intern als Binärzahl gesehen, dann muss doch eine Schleife existieren, in der bei der Variablen zahl von Bit zu Bit gegangen wird um zu prüfen, ob hier eine Ziffer 1 steht.
Der Operator &
& bitweises UND Beispiel i & 7 // was bedeutet dies.
Und wie ist der Klammerwert zu lesen?
Was bedeutet hier: 1 Bit nach links schieben in Bezug auf k? Die Variable k wird doch schon um jeden Schleifendurchgang um eins kleiner und dann noch einmal um 1 Bit verschieben?
Kann mir jemand auf die Sprünge helfen?
Terep |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 17.05.2008, 12:50 Titel: Re: Bit-Operatoren |
|
|
Terep hat Folgendes geschrieben: |
Erst dachte ich, dass ich die Verwendung von Bit-Operatoren verstehe. |
Da lagst du wohl komplett falsch! :p
Terep hat Folgendes geschrieben: |
wird Zahl intern als Binärzahl gesehen, dann muss doch eine Schleife existieren |
Bit Operatoren lassen sich mit allen Integralen Typen verwenden (char, short, int, long, ...). Da die CPU die Zahl ohnehin nur als "binäres Muster" kennt muss da nicht viel "intern gesehen" werden.
Terep hat Folgendes geschrieben: |
in der bei der Variablen zahl von Bit zu Bit gegangen wird um zu prüfen, ob hier eine Ziffer 1 steht. |
Wird ja: for (int k = anzahlDerBits - 1; k >= 0; --k)
Terep hat Folgendes geschrieben: |
Der Operator &
& bitweises UND Beispiel i & 7 // was bedeutet dies. |
Mit dem Operator kannst du Bitsets pet UND verknüpfen. Am einfachen Beispiel:
CPP: | 0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1
|
Der Operator liefert also nur dann ein gesetztes Bit, wenn beide verknüpften Bits gesetzt sind. Das funktioniert natürlich auch mit komplexeren "Bitsets":
CPP: | 12658 = 11000101110010 im Dualsystem
8873 = 10001010101001 im Dualsystem
11000101110010
& 10001010101001
----------------------
10000000100000 = 8224 im Dezimalsystem
|
Terep hat Folgendes geschrieben: |
Und wie ist der Klammerwert zu lesen? |
So wie du alle Klammern lesen würdest:
"wenn das Ergebniss der Bitweisen UND Verknüpfung von 'zahl' mit dem Wert, 1 um 'k' Stellen nach links geschoben, ungleich null ist, dann..."
Terep hat Folgendes geschrieben: |
Was bedeutet hier: 1 Bit nach links schieben in Bezug auf k? Die Variable k wird doch schon um jeden Schleifendurchgang um eins kleiner und dann noch einmal um 1 Bit verschieben? |
Damit erstellst du Zahlen bei denen immer das 'k'-te Bit gesetzt ist. Zum Beispiel:
CPP: | for ( int i = 5; i >= 0; --i )
printf( "%d\n", ( 1 << i ) );
|
Das würde folgende Ausgabe ergeben (zusätzlich mit Binärdarstellung):
Zitat: |
32 = (100000)
16 = (10000)
8 = (1000)
4 = (100)
2 = (10)
1 = (1)
|
Wenn du jetzt diese 'power of two' Zahlen mit deiner 'zahl' per UND verknüpfst bekommst du immer dann ein Ergebnis ungleich Null wenn dieses Bit in 'zahl' gesetzt ist.
Terep hat Folgendes geschrieben: |
Kann mir jemand auf die Sprünge helfen?
Terep |
Hoffentlich... |
|
Nach oben |
|
|
Terep Mini JLI'ler
Anmeldedatum: 02.05.2008 Beiträge: 18 Wohnort: Hannover Medaillen: Keine
|
Verfasst am: 17.05.2008, 20:39 Titel: |
|
|
Ich habe es aufgearbeitet und so verstanden:
Zu: Integrale Typen (den Begriff habe ich in C++ vorher nicht wahrgenommen)
Variable wie char, signed char, unsigned char, short int oder unsigned short int lassen sich ohne Informationsverfälschung in einen Integerwert int umsetzen und sind untereinander konvertierbar (Typänderung).
Dies ist möglich, da sie alle als „binäres Muster“ wie folgt hinterlegt hat. Zum Beispiel 151:
Binär 1 0 0 1 0 1 1 1
dezimal 128 0 0 16 0 4 2 1
Index k 7 6 5 4 3 2 1 0
Ist das Bit mit 1 gesetzt wird die entsprechende 2er Potenz hinterlegt. Bei Null eben 0.
Die for-Schleife startet mit AnzahlderBits -1. das heißt hier mit 7 starten und pro Schleife um eins dekrementieren bis einschließlich Null.
Der Operator & (bitweises und) übernimmt die Funktion der Aussagenlogik (und): wenn A und B zugleich wahr sind dann und nur dann ist die Aussage wahr.
In dieser if-Bedingung:
if (zahl & (1 << k))
Aussage A: Wenn der Index k der Zahl eine 1 hat, ist die Aussage A wahr
Aussage B: hier kommt es um eine bitweise Verschiebung um k-stellen. Wenn Aussage
A wahr ist, setzt der &-Operator eine 1, dann ist die Aussage B wahr
Somit ist die if-Bedingung wahr und verzweigt zur Bildschirmausgabe für eine 1 ansonsten im else-Fall eine 0.
Schwierigkeiten im Verständnis habe ich mit der Aussage B. Inhaltlich würde ich es so formulieren. Wenn der Index k bei der Zahl eine 1 hat, ist die Bedingung wahr; und fertig ist es.
Hier sieht es so aus, als ob noch zusätzlich ein zweiter Term (1<<k) da ist. Das heißt, ich habe es immer noch nicht kapiert. Es sieht für mich so aus, wenn der Index k eine 1 hat, setze bei der Bitverschiebung 1<<k entsprechend eine 1. Das gehört dann aber nicht in die if-Bedingung sondern in die Ausführung wenn die Bedingung wahr ist.
Du sagst aber:
Der Operator liefert also nur dann ein gesetztes Bit, wenn beide verknüpften Bits gesetzt sind
Wo ist hier die zweite Bedingung? Wo ist das zweite Bitset?
Auf jeden Fall danke ich Dir für die Reaktion!
Leider brauche ich die Ehrenrunde, da ich es noch nicht verstanden habe.
Terep
PS was meinst Du mit "pet" bei „Mit dem Operator kannst du Bitsets pet UND verknüpfen. Am einfachen Beispiel: „ |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 17.05.2008, 23:08 Titel: |
|
|
Also nochmal langsam:
Du verknüpfst immer zwei Bitsets per Bitoperator. Das eine ist die Zahl das andere ergibt sich aus (1<<k). Da k sich bei jedem Schleifendurchlauf ändert bekommst du immer andere Werte, nämlich Potenzen von Zwei.
Also: Erst wird die Eins um 'k' Stellen nach links geschoben und dann wird das Ergebnis mit 'zahl' per Und verknüpft.
grüße
P.S.: 'pet' ist ein falsch geschriebenes 'per'. |
|
Nach oben |
|
|
Terep Mini JLI'ler
Anmeldedatum: 02.05.2008 Beiträge: 18 Wohnort: Hannover Medaillen: Keine
|
Verfasst am: 18.05.2008, 05:46 Titel: |
|
|
Bitset 1: Ist die Variable zahl
Bitset 2 der Ausdruck 1 << k
Der Verschiebeoperator << schiebt mit jedem Schleifendurchgang um 1 Stelle nach links und gibt die jeweilige 2er Potenz 1, 2, 4, 8 usw. an, wenn die eins gesetzt wird.
Besonderheit: Es findet nicht offiziell in der Art wie „k = 1“ statt.
Sondern der Bitoperator & übernimmt das Ergebnis k = 1 bzw. 0 je nach Schleifenergebnis für den Folgeterm.
Daher gibt es noch 3 weitere Bitoperatoren, die entsprechend anders verknüpfen und so den Term 1 << k zu einem anderen Bitset führen würden.
Der Operator & steht also nicht als reines Auswertungskriterium wie bei der Aussagenlogik zur Verfügung sondern wirkt mit der Verknüpfung & auf den Folgeterm so ein, dass ein Ergebnis in Bezug auf 0 oder 1 wie bei der Aussagelogik "und" eintritt.
Somit habe ich 2 Bitsets, die bei Verwendung von k = 1 true ausgeben. Mehr ist nicht.
Ich hoffe, dem ist so, und ich habe Deine Ausführungen richtig umgesetzt. Ansonsten brauche ich wohl noch eine Ehrenrunde.
Jedenfalls regt Dein Kommentar stark zum Denken und Nachvollziehen an. Dafür danke.
Terep |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 18.05.2008, 06:55 Titel: |
|
|
Der &-Operator ist schon Auswertungskriterium. Der Idee hinter der &-Verknüpfung haben wir ja bereits geklärt.
Nehmen wir z.B. zwei Bitsets, A und B. A kann jede beliebige Zahl im Dualen System darstellen, B ist eine Zweierpotenz.
Das besondere an Zweierpotenzen ist, das diesen immer nur ein Bit gesetzt ist:
CPP: | 00000001 = 1
00000010 = 2
00000100 = 4
00001000 = 8
00010000 = 16
00100000 = 32
01000000 = 64
10000000 = 128
|
Wenn wir also eine solche Zweierpotenz mit A verknüpfen werden alle Bits gelöscht. Mit ausnahme des in B gesetzten Bits, allerdings bleibt das nur dann erhalten wenn genau dieses Bit auch in A gesetzt ist:
Bit 5 ist in 2795 nicht gesetzt:
CPP: | 0101011101011
& 0000000010000
--------------------
0000000000000
|
Aber Bit 4 ist in 2795 gesetzt:
CPP: | 0101011101011
& 0000000001000
--------------------
0000000001000
|
Wir sehen also. Beim verknüpfen einer beliebigen Zahl und einer Zweierpotenz gibt es zwei Ergebnise:
Entwerder 0: dann ist das eine Bit nicht gesetzt.
Oder den Wert der Zweierpotenz: dann ist das Bit gesetzt.
Durch die Klammer um 1<<k wird der Ausdruck zuerst ausgewertet und dann mit 'zahl' verknüpft, d.h. das Ergebnis (!) von 1 << k wird mit zahl verknüpft und hat beim weiteren Auswerten keine Relevanz mehr.
Ausgeschrieben sähe die Abfrage so aus:
CPP: | if (zahl & 32768) //...
if (zahl & 16384) //...
if (zahl & 8192) //...
if (zahl & 4096) //...
if (zahl & 2048) //...
if (zahl & 1024) //...
if (zahl & 512) //...
if (zahl & 256) //...
if (zahl & 128) //...
if (zahl & 64) //...
if (zahl & 32) //...
if (zahl & 16) //...
if (zahl & 8) //...
if (zahl & 4) //...
if (zahl & 2) //...
if (zahl & 1) //... |
Das funktioniert weil C++ jeden Wert ungleich Null als wahr betrachtet. Wenn mans genau nimmt müsste die Abfrage wie folgt aussehen:
CPP: | int mask = 1 << k; // zweierpotenz 2^k
if ( ( zahl & mask ) == mask )
printf( "1" );
else
printf( "0" );
|
Da C++ aber Null als unwahr und Werte ungleich Null als wahr betrachtet reicht auch die Version:
CPP: | if ( zahl & ( 1 << k ) )
printf( "1" );
else
printf( "0" );
|
Ich hoffe mal das jetzt alle Unklarheiten aus dem Weg geräumt sind. |
|
Nach oben |
|
|
Terep Mini JLI'ler
Anmeldedatum: 02.05.2008 Beiträge: 18 Wohnort: Hannover Medaillen: Keine
|
Verfasst am: 18.05.2008, 09:45 Titel: |
|
|
Das Gefühl der Schwammigkeit bzgl. des Zustandekommens des Bitfelds 2 existiert nicht mehr.
Gemäß Deinen Ausführungen ist der Bitoperator in seiner Funktion doch „nur“ das logische „und“ der Aussagenlogik und ich kann es jetzt (!) nachvollziehen:
Der Ablauf in C++ pro for-Schleife für die Bedingung: if (zahl & (1 << k))
Zuerst wird der Term zahl geprüft, wenn das Ergebnis true ist, prüft C++ den UND-Fall.
Ist das Ergebnis Null = false wird die Bedingungsprüfung abgebrochen, da das Ergebnis false steht und es geht bei else weiter.
zahl = Aussage A: Es wird bei Bit k geprüft, ob bei der Variablen zahl in der Bitposition k eine 1 gesetzt ist. Wenn ja = true.
Wenn Aussage A gleich true ist, prüft C++ die 2. Aussage:
(1 << k) = Aussage B: hier wird die 2er-Potenz der entsprechenden k-Position im Bitfeld errechnet. Demzufolge hat die Aussage B immer den Boolwert = true da alles ungleich Null true ist.
Ist Aussage A und B true, setzt der Operator & die if-Bedingung auf true und auch nur dann auf true.
Es geht im Programm weiter.
Anders ausgedrückt, der Operator & braucht 2 Bitsets.
Also gibt man den Term (1 << k) dazu und schon hat man, was man braucht.
Das zu verstehen ist schon schwer genug, das zu entwickeln ist genial.
Jetzt wirkt es auf mich einfach. Wieso brauche ich solange um das zu kapieren? Ich denke, dass ich keine weitere Ehrenrunde brauche.
Danke für Deine Kondition mir den Sachverhalt kopfmäßig nachvollziehen zu lassen.
Terep |
|
Nach oben |
|
|
David Super JLI'ler
Alter: 39 Anmeldedatum: 13.10.2005 Beiträge: 315
Medaillen: Keine
|
Verfasst am: 18.05.2008, 11:21 Titel: |
|
|
Du siehst das immer noch ein wenig zu kompliziert. Der &-Operator ist nicht der logische &&-Operator. Es gibt in diesem Fall nur ein Kriterium für die If-Anweisung, nämlich das Ergebnis der bitweisen Verknüpfung von 'zahl' und (1<<k).
Vom Ablauf her ist das wie folgt:
(Angenommen: k = 15, zahl = 1001000110000110)
Zitat: |
o if ( zahl & ( 1<<k ) ) ---> 1<<k = 32768
o if ( zahl & 32768 )
---> 37254 & 32768
1001000110000110
& 1000000000000000
-------------------------
1000000000000000 = 32768 => ungleich 0
o if ( 32768 ) --> bit ist Gesetzt
|
(Angenommen: k = 14, zahl = 1001000110000110)
Zitat: |
o if ( zahl & ( 1<<k ) ) ---> 1<<k = 16384
o if ( zahl & 16384)
---> 37254 & 16384
1001000110000110
& 0100000000000000
-------------------------
0000000000000000 = 0 => gleich 0
o if ( 0 ) --> bit ist nicht Gesetzt
|
|
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|