none
Integer oder enum bitweise prüfen RRS feed

  • Frage

  • Hallo Community,
    ich möchte einen Integer nach dessen Wert bitweise abprüfen.
    Das geht so nicht.
    int z = Config.mode | 4;
    if (Config.mode == 0 || (Config.mode | 4))
    {
     return;
    }

    Der Config.mode kann Werte von 0 bis 7 aufweisen.
    Trennung ist die 4, sprich das 3 Bit.
    Dann dachte ich, ich nehme ein enum und prüfe es wie folgt.
    int in enum wandeln.
    (Possibilities)Config.mode == ((Possibilities)Config.mode & Possibilities.Type1 )

    geht auch nicht.

    Kurzum, ich brauche kurz Hilfe.
    Danke für Tipps.

    Das Ziel ist einfach.

    • 0000
    • 0001
    • 0010
    • 0100   Das 4 Bit gilt als Gruppierung, das ist der Grund.
    • 0101
    • 0110
    • 0111
    Grüße Markus
    byte b1 = 0xCD; // 0xCD = 205                   = 11001101
    byte b2 = 0x6A; // 0x6A = 106                   = 01101010
    
    
    byte erg1 = (byte)(b1 | 4); // 0xEF = 239 = 11101111
    Console.Out.WriteLine("{0:X2}", erg1);
    
    
    
    
    [Flags()]
    public enum Decide : uint
    {
     None = 0,
     Later = 1,
     Later2 = 2,
     CheckAdjustment = 4,
     In2010 = 8
     
    }
    
    
    [Flags()]
    public enum Possibilities
    {
     NotWritten = 0,
     All = 1,
     Type1 = 2,
     Type2 = 3,
    
    
     ToHarddiskCheck = 4,
    
    
     TempAll = 5,
     TempType1 = 6,
     TempHarddiskCheck = 7
    }

    Freitag, 10. Juni 2016 15:18

Antworten

  • Hallo Markus, wenn ich das noch einmal zusammenfasse,...

    ich lese aus der App.config den Integerwert z.B. 3.

    Möchte nun prüfen

    0000

    0001
    0010
    0100 Das 4 Bit gilt als Gruppierung, das ist der Grund.
    0101
    0110
    0111

    ist der Wert oberhalb oder unterhalb der 'sogenannten' Gruppe.

    Also wenn der Configwert 7 ist, teste bitweise mit der 4, weiß ich, ich bin unterhalb.

    und...

    public enum Possibilities
    {
     NotWritten = 0,
     All = 1,
     Type1 = 2,
     Type2 = 3,
     ToHarddiskCheck = 4, // obere oder untere Hälfte
     TempAll = 5,
     TempType1 = 6,
     TempHarddiskCheck = 7
    }
    • ... Ich will einfach obere/untere Hälfte(Gruppe) prüfen, ...

    ... willst du also scheinbar nur wissen, ob dein eingelesener Config-Wert kleiner, gleich oder größer 4 ist.

    Dann weißt du, ob du oberhalb, auf dem Punkt oder unterhalb bist.

    Also, wozu eigentlich die ganze Bit-Testerei?

    bool obererTeil = (Possibilities)ConfigMode < Possibilities.ToHarddiskCheck;
    bool Grenze = (Possibilities)ConfigMode == Possibilities.ToHarddiskCheck;
    bool untereTeil = (Possibilities)ConfigMode > Possibilities.ToHarddiskCheck;
    Gruß

    • Als Antwort markiert MarkusMayer Sonntag, 12. Juni 2016 13:34
    Samstag, 11. Juni 2016 07:58
  • Hallo,

    um zu testen ob ein Bit gesetzt ist, verwendet man ein binäres Und "&"  - kein Oder "|", denn das setzt den Wert, und wäre immer wahr, also

    if ((Config.mode == 0) || ((Config.mode & 4) != 0))
    {
      return ;
    }
    wobei man je nach Geschmack auch auf == 4 testen könnte.

    Im übrigen erlauben Enumerationen über das Flags Attribut mehrere Bits zusammen zu fassen / zu testen, siehe auch: http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c.

    Gruß Elmar

    • Als Antwort markiert MarkusMayer Montag, 13. Juni 2016 16:30
    Montag, 13. Juni 2016 13:34
    Beantworter
  • Hallo Markus,

    du kannst mit "geflagter" Enum genau dasselbe machen wie mit den anderen Bitoperationen. Du musst nur daran denken, dass die Prüfung auf das MSB deine Enum nur dann in zwei Hälften teilt (zur oberen Hälfte gehörend...), wenn die "Bitbreite" ausgeschöpft wird.

    In deinem Fall hast du quasi eine 3-Bit Zahl, dezimal 0 bis 7 oder binär 000 bis 111. Würdest du jetzt die Enum um eine Position erweitern, also den Wert 8... einführen, schlägt dein Konzept fehl. Du hättest dann quasi eine 4-Bit breite Zahl, das MSB teilt aber nicht mehr die Gruppe, da die Werte 9-15 fehlen.

    Also, bei der Frage die sich dir stellt, läuft ja alles eigentlich auf "ist größer, gleich oder keiner als" hinaus, und dafür gibt es die schlichten Vergleichsoperatoren.

    Ich meine, die "geflagte" Enum macht Sinn, falls mehrere Optionen zeitgleich gesetzt sein können und/oder du gezielt bestimmte Kombinationen abfragen möchtest. Dann müsstest du die Enumeration allerdings etwas anders aufbauen, da jede Kombination eine eindeutige Summe erfordert und deine Werte könnten statt 0,1,...,7 dann 0,1,2,4,8,16,32,64 lauten.

    Als Ergänzung: mit..

    [Flags]
    public enum PBF {
    	NotWritten = 0,
    	All = 1,
    	Type1 = 2,
    	Type2 = 3,
    	ToHarddiskCheck = 4,
    	TempAll = 5,
    	TempType1 = 6,
    	TempHarddiskCheck = 7,
    	UngünstigJetzt = 8 // <---
    }

    und

    for ( ConfigMode = 0 ; ConfigMode < 9 ; ConfigMode++ ) {
    	Console.WriteLine($"HasFlag: {((PBF)ConfigMode).HasFlag(PBF.ToHarddiskCheck)}");
    }
    Console.ReadKey();

    lässt sich das, was ich meine, vielleicht verdeutlichen.

    Gruß

    • Als Antwort markiert MarkusMayer Dienstag, 14. Juni 2016 16:24
    Montag, 13. Juni 2016 23:26

Alle Antworten

  • Hi Markus,
    so richtig verstanden habe ich nicht, was Du ermitteln willst, deshalb hier mal eine Anregung:

          byte b1 = 0xCD; // 0xCD = 205                   = 11001101
          byte b2 = 0x6A; // 0x6A = 106                   = 01101010
    
          var res1 = b1 | b2; // bitweises Oder
          var res2 = b1 & b2; // bitweises Und
          var res3 = b1 ^ b2; // bitweises exclusives Oder
          Console.WriteLine(res1);
          Console.WriteLine(res2);
          Console.WriteLine(res3);
          Console.WriteLine($"Bit 04 in b1 ein: {(b1 & 4) != 0}");
          Console.WriteLine($"Bit 04 in b2 ein: {(b2 & 4) != 0}");


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.

    Freitag, 10. Juni 2016 15:31
  • Hallo Peter,

    int z = Config.mode | 4;
    if (Config.mode == 0 || (Config.mode | 4))
    {
     return;
    }

    ich lese aus der App.config den Integerwert z.B. 3.

    Möchte nun prüfen

    0000

    • 0001
    • 0010
    • 0100   Das 4 Bit gilt als Gruppierung, das ist der Grund.
    • 0101
    • 0110
    • 0111

    ist der Wert oberhalb oder unterhalb der 'sogenannten' Gruppe.

    Also wenn der Configwert 7 ist, teste bitweise mit der 4, weiß ich, ich bin unterhalb.

    Wie macht man das in C#? Klar?

    If geht nicht, kommt immer kann nicht auf bool prüfen. In C++ geht es wie oben beschrieben.

    Grüße Markus

    Freitag, 10. Juni 2016 15:50
  • Hallo,

    vielleicht hilft dies weiter:

    int ConfigMode = Convert.ToInt32("1110", 2);
    string bin = Convert.ToString(ConfigMode, 2);
    for ( int position = 0 ; position < bin.Length ; position++){
      bool gesetzt = (ConfigMode & (1 << position)) > 0;
      Console.WriteLine($"Bit an Position {position} in {bin} ist gesetzt: {gesetzt}");
    }
    Console.ReadKey();
    Gruß

    Freitag, 10. Juni 2016 18:27
  • Hi Markus,
    das geht in C# genau so mit dem Unterschied, dass in C++ ein Byte mit 0-Bits als false gewertet wird. Das ist in C# zu konvertieren:

    if (Config.mode == 0 || (Config.mode | 4) == 0 )

    
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.

    Freitag, 10. Juni 2016 19:48
  • Hallo Markus,

    so lang und aufwändig ist das nun nicht, oder?

    Also, wenn du testen willst, ob ConfigMode 0 ist oder in ConfigMode das dritte Bit gesetzt ist, so habe ich die Frage richtig verstanden?

    ConfigMode == 0 || (ConfigMode & (1 << position)) > 0

    So kannst du die Position angeben, du kannst natürlich statt 1 << 2 (für die dritte Position) auch, wie Peter gezeigt hat, direkt 4 angeben, also

    ConfigMode == 0 || (ConfigMode & 4) > 0


    Gruß



    • Bearbeitet K. Pater Freitag, 10. Juni 2016 21:09
    Freitag, 10. Juni 2016 21:02
  • Hi Markus,
    ich vermute, dass Dum mit dem Code Probleme bekommen wirst:

    (Config.mode | Possibilities.ToHarddiskCheck ) == 1

    Da hier ein ODER ausgeführt wird, ist das Ergebnis wahr, wenn entweder Config.mode an irgendeiner Stelle ein gesetztes Bit hat oder, falls Config.mode kein gesetztes Bit hat, Possibilities.ToHarddiskCheck ein gesetztes Bit hat. Aus Deinen Ausführungen vermute ich, dass Du ein UND an dieser Stelle benötigst.


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.

    Samstag, 11. Juni 2016 06:29
  • Hallo Markus, wenn ich das noch einmal zusammenfasse,...

    ich lese aus der App.config den Integerwert z.B. 3.

    Möchte nun prüfen

    0000

    0001
    0010
    0100 Das 4 Bit gilt als Gruppierung, das ist der Grund.
    0101
    0110
    0111

    ist der Wert oberhalb oder unterhalb der 'sogenannten' Gruppe.

    Also wenn der Configwert 7 ist, teste bitweise mit der 4, weiß ich, ich bin unterhalb.

    und...

    public enum Possibilities
    {
     NotWritten = 0,
     All = 1,
     Type1 = 2,
     Type2 = 3,
     ToHarddiskCheck = 4, // obere oder untere Hälfte
     TempAll = 5,
     TempType1 = 6,
     TempHarddiskCheck = 7
    }
    • ... Ich will einfach obere/untere Hälfte(Gruppe) prüfen, ...

    ... willst du also scheinbar nur wissen, ob dein eingelesener Config-Wert kleiner, gleich oder größer 4 ist.

    Dann weißt du, ob du oberhalb, auf dem Punkt oder unterhalb bist.

    Also, wozu eigentlich die ganze Bit-Testerei?

    bool obererTeil = (Possibilities)ConfigMode < Possibilities.ToHarddiskCheck;
    bool Grenze = (Possibilities)ConfigMode == Possibilities.ToHarddiskCheck;
    bool untereTeil = (Possibilities)ConfigMode > Possibilities.ToHarddiskCheck;
    Gruß

    • Als Antwort markiert MarkusMayer Sonntag, 12. Juni 2016 13:34
    Samstag, 11. Juni 2016 07:58
  • if (Config.mode == 0 || (Config.mode | 4) == 0 )

    
    

    Hi Peter,

    was genau prüfst du mit dem Ausdruck?

    Gruß

    Samstag, 11. Juni 2016 08:11
  • Hi, 

    versuch es doch so:

    var bit = (Config.mode & (1 << bitNumber-1)) != 0;

    ...also mit Bit-Shifting.

    Gruß

    Samstag, 11. Juni 2016 08:23
  • Also, wozu eigentlich die ganze Bit-Testerei?

    bool obererTeil = (Possibilities)ConfigMode < Possibilities.ToHarddiskCheck;
    bool Grenze = (Possibilities)ConfigMode == Possibilities.ToHarddiskCheck;
    bool untereTeil = (Possibilities)ConfigMode > Possibilities.ToHarddiskCheck;

    Hallo K. Pater,

    ja Du hast Recht.

    [Flags()]
    public enum Possibilities
    {
     NotWritten = 0,
     All = 1,
     Type1 = 2,
     Type2 = 3,
     ToHarddiskCheck = 4, // obere oder untere Hälfte
     TempAll = 5,
     TempType1 = 6,
     TempHarddiskCheck = 7
    }

    so würde es auch gehen, ohne Bittesterei. Man merkt auch hier, so einfach ist das nicht;-)

    Das Problem ist so gelöst. Ich lasse den Thread noch offen, rein interessehalber, vielleicht weiß jemand noch was, gerne mit Bittesterei, Bitschieberei, vielleicht kann man es mal brauchen.

    Wie gesagt Danke an Allen mal.

    int in enum, einfach casten - beantwortet

    das Ziel - beantwortet

    Vielleicht noch wo liegt der Unterschied, wenn ich bei enum Flags davorstelle.

    Geht das ohne dann gar nicht, bitweise prüfen?

    Grüße Markus

    Samstag, 11. Juni 2016 10:24
  • Hi Klaus,
    ich prüfe da nix. Das war die Übersetzung von C++ nach C# der Anweisung aus dem Post vom Markus, welches inzwischen gelöscht ist. Der Sinn dieser Logik erschließt sich mir nicht. Ich weiß auch nicht, was Markus da im C++-Programm gemacht hatte.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.

    Samstag, 11. Juni 2016 17:52
  • Hallo Zusammen,

    bool obererTeil = (Possibilities)ConfigMode < Possibilities.ToHarddiskCheck;
    bool Grenze = (Possibilities)ConfigMode == Possibilities.ToHarddiskCheck;
    bool untereTeil = (Possibilities)ConfigMode > Possibilities.ToHarddiskCheck;

    ich denke das ist die Lösung. Alternativ wäre es noch nett, wenn Ihr mir ein Beispiel mit den Flag parat hättet.

    Um nicht für Verwirrung zu sorgen, habe ich ein Posting gelöscht.

    Viele Grüße Markus und DANKE.

    Sonntag, 12. Juni 2016 13:34

  • ich prüfe da nix. Das war die Übersetzung von C++ nach C# der Anweisung aus dem Post vom Markus, welches inzwischen gelöscht ist. Der Sinn dieser Logik erschließt sich mir nicht. Ich weiß auch nicht, was Markus da im C++-Programm gemacht hatte.

    Hallo Peter,

    wie Klaus erkannte lediglich eine Grenze oben und unten  -- 4 ist das Entscheidungsbit.

    Grüße Markus

    int z = Config.mode | 4;
    if (Config.mode == 0 || (Config.mode | 4))
    {
     return;
    }

    Sonntag, 12. Juni 2016 13:36
  • Hi Markus

    int z = Config.mode | 4;
    if (Config.mode == 0 || (Config.mode | 4))
    {
     return;
    }

    Mit dem nachfolgenden Code kannst Du den Unsinn dieser Anweisung darstellen:

    using System;
    
    namespace ConsoleApplication8
    {
      class Program
      {
        static void Main(string[] args)
        {
          for (byte i = 0; i < 15; i++)
          {
            Config.mode = i;
            Console.WriteLine($"{i} {TestSub()}");
          }
          Console.ReadKey();
        }
        private static bool TestSub()
        {
          if (Config.mode == 0 || (Config.mode | 4) != 0)
          {
            return true;
          }
          return false;
        }
        internal static class Config
        {
          internal static byte mode { get; set; }
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen! Leben retten!
    Wir essen Opa.
    Wir essen, Opa.

    Sonntag, 12. Juni 2016 17:19
  • Hallo,

    um zu testen ob ein Bit gesetzt ist, verwendet man ein binäres Und "&"  - kein Oder "|", denn das setzt den Wert, und wäre immer wahr, also

    if ((Config.mode == 0) || ((Config.mode & 4) != 0))
    {
      return ;
    }
    wobei man je nach Geschmack auch auf == 4 testen könnte.

    Im übrigen erlauben Enumerationen über das Flags Attribut mehrere Bits zusammen zu fassen / zu testen, siehe auch: http://stackoverflow.com/questions/8447/what-does-the-flags-enum-attribute-mean-in-c.

    Gruß Elmar

    • Als Antwort markiert MarkusMayer Montag, 13. Juni 2016 16:30
    Montag, 13. Juni 2016 13:34
    Beantworter
  • Hallo,

    wann nehme ich Flags, wann nicht.
    Nur als Hilfe fürs debuggen? Das Ergebnis ist das Gleiche.

    BTE.Possibilities test;
    test = BTE.Possibilities.TempHarddiskCheck;
    b1 = (test == BTE.Possibilities.NotWritten);
    b2 = ((test & BTE.Possibilities.ToHarddiskCheck) == BTE.Possibilities.ToHarddiskCheck);
    
    //  [Flags()]
    public enum Possibilities
    {
    	NotWritten = 0,
    	All = 1,
    	Type1 = 2,
    	Type2 = 3,
    	ToHarddiskCheck = 4, // obere oder untere Hälfte
    	TempAll = 5,
    	TempType1 = 6,
    	TempHarddiskCheck = 7
    }

    Mit - sehr schön zu sehen.

    a

    Ohne mit gleichem Ergebnis.

    vv


    Wenn der Mode 5 aufweist, ist es mit Flag     All | ToHarddiskCheck
                                     ohne Flag    TempAll
    Grüße Markus

    Montag, 13. Juni 2016 16:30
  • Hallo Markus,

    du kannst mit "geflagter" Enum genau dasselbe machen wie mit den anderen Bitoperationen. Du musst nur daran denken, dass die Prüfung auf das MSB deine Enum nur dann in zwei Hälften teilt (zur oberen Hälfte gehörend...), wenn die "Bitbreite" ausgeschöpft wird.

    In deinem Fall hast du quasi eine 3-Bit Zahl, dezimal 0 bis 7 oder binär 000 bis 111. Würdest du jetzt die Enum um eine Position erweitern, also den Wert 8... einführen, schlägt dein Konzept fehl. Du hättest dann quasi eine 4-Bit breite Zahl, das MSB teilt aber nicht mehr die Gruppe, da die Werte 9-15 fehlen.

    Also, bei der Frage die sich dir stellt, läuft ja alles eigentlich auf "ist größer, gleich oder keiner als" hinaus, und dafür gibt es die schlichten Vergleichsoperatoren.

    Ich meine, die "geflagte" Enum macht Sinn, falls mehrere Optionen zeitgleich gesetzt sein können und/oder du gezielt bestimmte Kombinationen abfragen möchtest. Dann müsstest du die Enumeration allerdings etwas anders aufbauen, da jede Kombination eine eindeutige Summe erfordert und deine Werte könnten statt 0,1,...,7 dann 0,1,2,4,8,16,32,64 lauten.

    Als Ergänzung: mit..

    [Flags]
    public enum PBF {
    	NotWritten = 0,
    	All = 1,
    	Type1 = 2,
    	Type2 = 3,
    	ToHarddiskCheck = 4,
    	TempAll = 5,
    	TempType1 = 6,
    	TempHarddiskCheck = 7,
    	UngünstigJetzt = 8 // <---
    }

    und

    for ( ConfigMode = 0 ; ConfigMode < 9 ; ConfigMode++ ) {
    	Console.WriteLine($"HasFlag: {((PBF)ConfigMode).HasFlag(PBF.ToHarddiskCheck)}");
    }
    Console.ReadKey();

    lässt sich das, was ich meine, vielleicht verdeutlichen.

    Gruß

    • Als Antwort markiert MarkusMayer Dienstag, 14. Juni 2016 16:24
    Montag, 13. Juni 2016 23:26
  • lässt sich das, was ich meine, vielleicht verdeutlichen.

    Hallo K. Pater,

    Danke für die Aufführung. Passt und war hilfreich.

    Viele Grüße Markus

    Dienstag, 14. Juni 2016 16:26