Wie komm ich an die Bits ?



  • junix schrieb:

    MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ist doch Jacke wie Hose ob ich in diesem Fall bei BuiltIns ein pre increment oder ein post increment mache (C++ FAQ).

    The for statement:
    
    for(for-init-statement; conditionopt ; expressionopt)
    {
      statement
    }
    
    is equivalent to:
    
    {
      for-init-statement
      while(condition)
      {
        statement
        expression
      }
    }
    

    Es dürfte also (in diesem Fall bei built-ins) nichts ausmachen 😉 . btw gibt das Programm bei mir keine 0 zuviel aus.



  • MaSTaH schrieb:

    junix schrieb:

    MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ist doch Jacke wie Hose ob ich in diesem Fall bei BuiltIns ein pre increment oder ein post increment mache (C++ FAQ).

    The for statement:
    
    for(for-init-statement; conditionopt ; expressionopt)
    {
      statement
    }
    
    is equivalent to:
    
    {
      for-init-statement
      while(condition)
      {
        statement
        expression
      }
    }
    

    Hmmm stimmt, hatte mich da vertan.

    -junix



  • Hab sowas auch schonmal geschrieben:

    #include <iostream.h>
    #include <fstream.h>
    #include <math.h>
    
    int main()
    {
       char buff,bits[8];
       ifstream datei("datei.txt");
       if(datei)
       {
          while(!datei.eof())
          {
             datei>>buff;
             if(!datei.eof())
             {
                for (int i=0;i<=7;i++)
                {
                   if(buff-pow(2,7-i)>=0)
                   {
                      buff-=pow(2,7-i);
                      bits[i]='1';
                   }
                   else bits[i]='0';
                   cout << bits[i];
                }
                cout << endl;
             }
          }
       }
       else cout << "Dateifehler !";
       datei.close();
       return 0;
    }
    


  • Danke für diesen Beitrag. Das ist aber so ziemlich das unperformanteste.... Bei Binärzahlen brauch ich doch kein POW!?!?!? Da schieb ich die Bits und gut ist. Jede Bitverschiebung nach links entspricht einem ^2.



  • Leute ihr müsst mir nochmal helfen. Ich hab ein bisschen nachgedahct, aber diese eine Schleife verstehe ich immer noch nicht richtig:

    for(int i=0;i<8;++i)
    {
        if(byte & 1)
            bits[i]='1';
        else
            bits[i]='0';
    
        byte>>=1;
    }
    

    1.: Wieso wird mit if(byte & 1) gerade das letzte Bit eines Bytes auf 1 geprüft ?

    2.: Was genau macht byte>>=1 ? Was wandert da wohin ?



  • Ich hab hier mal ne etwas andere Version des Programms. Es liest eine beliebige Datei ein und schreibt dann für jedes Zeichen das ihm folgende Zeichen in temp.txt. Aber es funktioniert nicht, sondern führt beim Ausführen zu "Fehler beim Lesen der Datei !". Wieso ?

    #include <iostream>
    #include <fstream>
    
    int main (int argc, char* argv[])
    {
    	using namespace std;
    
    	ifstream read(argv[1]);
    	ofstream write("temp.txt");
    	char byte;
    	int add;
    
    	cout<<endl;
    	if(read)
    	{
    		while(!read.eof())
    		{
    			read>>byte;
    			if(!read.fail())
    			{
    				if(int(byte)==255)
    					add=33;
    				else
    					add=int(byte)+1;
    
    				byte=char(add);
    				write<<byte;
    			}
    			else
    			{
    				cout<<"Fehler beim Lesen der Datei !"<<endl<<endl;
    				return 1;
    			}
    
    		}
    		cout<<endl<<endl;
    	}
    	else
    	{
    		cout<<"Datei nicht gefunden !"<<endl<<endl;
    	}
    
    return 0;
    }
    


  • 1.: Wieso wird mit if(byte & 1) gerade das letzte Bit eines Bytes auf 1 geprüft ?

    Dezimal 1 = hexadezimal 0x01 = binär 00000001

    Wenn ich also frage, ob die AND-Verknüpfung von byte und binär 00000001 = TRUE (=1) ist, dann führt das dazu, daß nur das niedrigste (das rechteste) Bit geprüft wird. Alle anderen Bits der Vergleichsmaske 00000001 sind ja 0 und können daher niemals 1 ergeben, weil

    1 AND 0 = 0
    0 AND 1 = 0
    1 AND 1 = 1

    ist. Die Aufgabe ist es ja, jeweils ein Bit daraufhin zu prüfen, ob es gesetzt ist oder nicht.

    2.: Was genau macht byte>>=1 ? Was wandert da wohin ?

    [/quote]
    Dieser Ausdruck ist der zweite Teil des Spiels. Zuvor hab ich ja das niedrigste Bit geprüft. Nun hab ich das getan und würde mir gerne auch die restlichen 7 Bits ankucken. Deshalb hab ich mich dazu entschieden, alle Bits in dem zu betrachtenden Byte um eine Stelle nach rechts zu bewegen. Das macht der ">>" Operator. Das ist praktisch das gleiche, wie wenn Du die dezimale 123 durch 10 dividierst. Was passiert hier? Die Zahl wird um eine Dezimalstelle nach rechts bewegt und das Komma um 1 Stelle nach links verschoben, wie das Ergebnis 12,3 eindrucksvoll zeigt.
    Da es bei int bzw. char Werten keine Nachkommastelle gibt, fällt das unterste Bit einfach weg und verschwindet im Nirgendwo.

    Also aus binär
    1001001101 wird nach >>= 1 der neue Binärwert
    0100100110.

    Ansonsten empfehle ich dringend das Studium passender Bücher über die C++ Sprache. Dort wird sowas auch erklärt und hilft, bessere Programme zu schreiben (wie das obige Beispiel mit pow() gezeigt hat, hat die Sache mit der Bitschieberei nicht jeder so richtig verstanden).



  • Vielen Dank für die ausführliche (und verständliche) Erklärung. Ich lerne aus einem Buch ("Objektorientiertes Programmieren in C++" von Nicolai Josuttis), aber da steht das leider so nicht drin. Also danke nochmal.

    Weiß einer wieso es bei dem abgeänderten Programm zu "Fehler beim Lesen der Datei !" kommt ?



  • Also ehrlich gesagt, hab ich das mit dem bitweisen AND und OR früher (so um 1830 herum) 😉 auch nie wirklich richtig verstanden, bis ich auf dem C64 mit Assembler begonnen hatte. Da war's dann plötzlich urklar.

    Deshalb kann man in C/C++ auch Multiplikationen/Divisionen mit 2, 4, 8, 16, 32, 64, 128 etc. dadurch umgehen, daß man die betreffende Zahl einfach x mal nach links (Multiplikation) bzw. rechts (Division) shiftet. Das macht die CPU deutlich schneller, als multiplizieren oder dividieren. Kann aber sein, daß der Compiler das bei seinen Optimierungen selber erkennt und macht (geht natürlich nur, wenn Konstante im Spiel sind und nich Variablen).

    Zu Deinem anderen Problem: Dir ist klar, daß Du eine Datei lesen willst, deren Name Du dem Programm als Parameter mitgeben mußt?



  • JFK schrieb:

    Deshalb kann man in C/C++ auch Multiplikationen/Divisionen mit 2, 4, 8, 16, 32, 64, 128 etc. dadurch umgehen, daß man die betreffende Zahl einfach x mal nach links (Multiplikation) bzw. rechts (Division) shiftet. Das macht die CPU deutlich schneller, als multiplizieren oder dividieren

    Was allerdings jetzt nicht heissen soll, dass man Multiplikationen in Zukunft statt mit "Var * 2" mit "Var <<= 2" codieren soll. Derartige Optimierungen übernehmen schon die billigsten Compiler. Ausserdem ist der Geschwindigkeitsvorteil im Vergleich zur Unlesbarkeit des Quelltextes minimal.

    -junix



  • Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt. Wenn ich nur die Binärwerte eines Zeichens WORDs oder Doppelworts haben möchte schreibe ich doch nicht alles Neu, oder ?

    Joe



  • JoeIntel schrieb:

    Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt.

    Hamma ned, wieso?

    -junix



  • junix schrieb:

    JoeIntel schrieb:

    Ich frage mich nur was ihr gegen die Funktion itoa und ihre anderen Implementierungen habt.

    Hamma ned, wieso?

    -junix

    Ach das war C++ Code was hier bis jetzt abgeliefert wurde , also bis auf cin war das nicht wirklich zu erkennen. Es gibt aber auch klassen die so etwas implementieren wenn ich mich nicht irre und die greifen dann auch auf itoa zu. Man ist nur ein bisschen elitärer als wenn mans gleich benutzt.

    Joe



  • Ich wüsste nicht, wo mir bei der Lösung des gestellten Problem itoa eine einfachere lösung sein sollte als die AND-Verknpüfung? Ich lass mir aber gern die Augen öffnen, wenn du was im Petto hast, lass und doch bitte Teilhaben...

    -junix



  • junix schrieb:

    Ich wüsste nicht, wo mir bei der Lösung des gestellten Problem itoa eine einfachere lösung sein sollte als die AND-Verknpüfung? Ich lass mir aber gern die Augen öffnen, wenn du was im Petto hast, lass und doch bitte Teilhaben...

    -junix

    nun ja ich für meinen Teil denek das es einige Vorteile dieser Funktion gibt. Die Frage war es doch wie bekomme ich die Bits ausgegeben und nicht wie schreibe ich eine tolle Funktion um die Bits auszugeben. Dies mach itoa perfekt und ausserdem für grössere eiheiten als Byte ich kann mir also vielleicht einige Schleifen sparen. Zweites vermeide ich Fehlerquellen wenn ich Funktionen aus Standardbibliotheken verwenden und kann davon ausgehen das diese auch optimiert sind. Wir sehen ja alle wie viele Fehler sich in diesem kurzen Stück Code einschleichen können und wie viele ansätze es gibt. Und drittens und nicht zu leztzt ist es kürzer einfacher und einfacher zu handhaben bzw. zu lesen.

    Dies alles sagt nichts über die Qualität eures Codes aus und ich will mir auch nicht erlauben ihn zu kritisieren aber es ist schon etwas länger als itoa(byte,ziel,2); oder von mir aus auch QString:arg(byte,0,2) ?
    Joe



  • itoa ist leider nicht in der Standardbibliothek.



  • Erschwerend kommt dazu, dass itoa ca. 6 mal langsamer ist als die oben vorgestellte variante.(hab mal ne Kurze Messung gemacht)

    -junix



  • und außerdem kann man "meine" Variante genausogut auch für 16-Bit und 32-Bit benutzen.... Dazu brauche ich auch nur eine Schleife und nicht mehr...



  • Wie schon gesagt ich bekrittele hier nicht den Code aber es gibt halt eine Funktion die es macht und zwar mit einem einzigen Aufruf. Das diese Funtkion langsamer ist ist mir jetzt auch klar da sie ja für alle Basen gilt (war ein kurzschluss). Trotzdem bleibe ich dabei lieber eine Funktion aus einer Bibliothek als tausend mal den selben Code schreiben. Soweit ich weiss gibt es auch in der c++ stdlib funktionen die dies machen. Also brauchen wir uns hier nicht um itoa rumsteiten. Ich wollte nur darauf hinweisen das man nicht immer alles neu schreiben muss und optimieren kann man fast alles immer noch wahrscheinlich auch deinen kurzen Code.

    Joe



  • junix schrieb:

    MaSTaH schrieb:

    junix schrieb:

    MaSTaH schrieb:

    Nö, ist doch im Prinzip richtig

    Wieso beschleicht mich nur das Gefühl, dass die Pre-Increments bei den beiden For was mit dem merkwürdigen Verhalten zu Tun haben?

    Ist doch Jacke wie Hose ob ich in diesem Fall bei BuiltIns ein pre increment oder ein post increment mache (C++ FAQ).

    The for statement:
    
    for(for-init-statement; conditionopt ; expressionopt)
    {
      statement
    }
    
    is equivalent to:
    
    {
      for-init-statement
      while(condition)
      {
        statement
        expression
      }
    }
    

    Hmmm stimmt, hatte mich da vertan.

    -junix

    Postet da nicht irgendwer immer den "Wie zitiere ich richtig im Usenet?"-Link? :p 😉


Anmelden zum Antworten