Java: Überprüfen, ob ein Bit in einer Länge 0 oder 1 ist

75

Mit welcher Methode würden Sie bestimmen, ob das Bit, das 2 ^ x darstellt, eine 1 oder 0 ist?

Ande Turner
quelle

Antworten:

179

Ich würde verwenden:

if ((value & (1L << x)) != 0)
{
   // The bit was set
}

(Möglicherweise können Sie mit weniger Klammern davonkommen, aber ich erinnere mich nie an den Vorrang bitweiser Operationen.)

Jon Skeet
quelle
52
Das hängt von der Sprache ab. In Java ist das nicht wahr.
Harmanjd
12
Das sollte 1L sein, oder (1 << 32) endet mit dem gleichen Wert wie (1 << 0)
mkb
4
@ThibThib nichts Seltsames daran. Bitte poste keinen dummen Anti-Java-Flammenköder.
Amischiefr
12
Ich frage mich, ob ((Wert >>> x) & 1)! = 0 besser ist, weil es keine Rolle spielt, ob der Wert lang ist oder nicht, oder ob es schlechter ist, weil es weniger offensichtlich ist.
Tom Hawtin - Tackline
4
@ArtOfWarfare: Ich habe manchmal falsch geschrieben ==als =- was dazu führt, dass ein gültiger Ausdruck diesen Wert zuweist, was nicht das ist , was ich will. In Java ist das illegal (vorausgesetzt, es ist keine booleanVariable). Bitweise Operatoren sind Teil von Java, und das ist gut so, IMO. Es gibt viele Situationen, in denen Sie bitweise Operatoren wünschen . Es gibt keine Notwendigkeit , das vermengen mit , ob der Typ eines Bedingungsausdruck in while, ifetc sein sollte boolean- was ich glaube , es sollte.
Jon Skeet
97

Eine andere Alternative:

if (BigInteger.valueOf(value).testBit(x)) {
    // ...
}
finnw
quelle
38
+1 für die Verwendung von Code, der für zukünftige Betreuer verständlich ist
cherouvim
9
Keine sehr gute Lösung, wenn dieser Code häufig aufgerufen wird. Sie ersetzen eine einzeilige Alternative durch eine einzeilige Alternative, und die Bitverschiebungen sind wirklich nicht so schwer.
wds
3
Zeilenlänge! = Lesbarkeit der Zeile, wds. Sie haben vielleicht Recht, dass die vorherige Lösung effizienter ist, aber der Unterschied ist wahrscheinlich gering, insbesondere wenn testBit () inline wird.
WCWedin
7
Es ist zu beachten, dass diese Lösung Speicher zuweist und viel weniger effizient ist als bitweise Operatoren. Ja, es spielt oft keine Rolle, aber manchmal ist es wichtig, unnötigen GC und / oder ineffizienten Code (Android-Apps, in der Hauptschleife eines Spiels usw.) zu vermeiden.
NateS
6
Ressourcenverschwendung. Wenn Sie den "zukünftigen Betreuern" nicht vertrauen können, um die Bitoperationen zu verstehen, haben Sie ein größeres Problem als das mit der Personalabteilung des Projekts. Bitoperationen sind keine Magie. Dies ist Teil der Grundkenntnisse eines Programmierers.
Dolmen
15

Ich frage mich, ob:

  if (((value >>> x) & 1) != 0) {

  }

.. ist besser, weil es egal ist, ob der Wert lang ist oder nicht, oder ob es schlechter ist, weil es weniger offensichtlich ist.

Tom Hawtin - Tackline 7. Juli um 14:16 Uhr

Ande
quelle
Ich denke, es ist besser, weil es weniger Fehlerpotential gibt - und wenn Sie denken, dass es nicht offensichtlich ist, können Sie den Test immer in eine entsprechend benannte Funktion extrahieren (boolesches isBitSet (langer Wert, int x) oder so)
hjhill
12

Sie können auch verwenden

bool isSet = ((value>>x) & 1) != 0;

BEARBEITEN: Der Unterschied zwischen " (value>>x) & 1" und " value & (1<<x)" hängt vom Verhalten ab, wenn x größer als die Größe des Typs "Wert" ist (in Ihrem Fall 32).

In diesem speziellen Fall haben Sie mit " (value>>x) & 1" das Vorzeichen des Werts, während Sie mit " value & (1<<x)" eine 0 erhalten (es ist manchmal nützlich, das Bitzeichen zu erhalten, wenn x zu groß ist).

Wenn Sie in diesem Fall eine 0 bevorzugen, können Sie >>>stattdessen den Operator " " verwenden, wenn " >>"

" ((value>>>x) & 1) != 0" Und " (value & (1<<x)) != 0" sind also völlig gleichwertig

ThibThib
quelle
8

Für das nth LSB (niedrigstwertiges Bit) sollte Folgendes funktionieren:

boolean isSet = (value & (1 << n)) != 0;
Noldorin
quelle
8
Das sollte 1L sein, oder (1 << 32) endet mit dem gleichen Wert wie (1 << 0)
mkb
4

In Java funktioniert Folgendes einwandfrei:

if (value << ~x < 0) {
   // xth bit set
} else {
   // xth bit not set
}

valueund xkann intoder sein long(und muss nicht gleich sein).

Vorsichtshinweis für Nicht-Java-Programmierer : Der vorhergehende Ausdruck funktioniert in Java, da in dieser Sprache die Bitverschiebungsoperatoren nur für die 5 (oder 6, falls long) niedrigsten Bits des rechten Operanden gelten. Dies übersetzt den Ausdruck implizit in value << (~x & 31)(oder value << (~x & 63)wenn valueja long).

Javascript : Es funktioniert auch in Javascript (wie bei Java werden nur die niedrigsten 5 Bits der Verschiebungsanzahl angewendet). In Javascript ist jede number32-Bit.

Insbesondere in C ruft eine negative Verschiebungszahl ein undefiniertes Verhalten hervor, sodass dieser Test nicht unbedingt funktioniert (obwohl dies abhängig von Ihrer speziellen Kombination aus Compiler / Prozessor möglich ist).

rslemos
quelle
2

Der Wert des 2 ^ x-Bits ist "Variable & (1 << x)".

Artur Soler
quelle
Wie Matt Kane in identischen Lösungen sagte: Das sollte 1L sein, oder (1 << 32) hat den gleichen Wert wie (1 << 0)
drvdijk
2

Wenn jemand mit bitweisen Operatoren nicht sehr vertraut ist, kann versucht werden, den folgenden Code programmgesteuert zu bestimmen. Es gibt zwei Möglichkeiten.

1) Verwenden Sie die Java-Sprachfunktion, um die Zeichenfolge im Binärformat abzurufen und das Zeichen an einer bestimmten Position zu überprüfen

2) Teilen Sie weiter durch 2 und bestimmen Sie den Bitwert an einer bestimmten Position.

public static void main(String[] args) {
    Integer n =1000;
    String binaryFormat =  Integer.toString(n, 2);
    int binaryFormatLength = binaryFormat.length();
    System.out.println("binaryFormat="+binaryFormat);
    for(int i = 1;i<10;i++){
        System.out.println("isBitSet("+n+","+i+")"+isBitSet(n,i));
        System.out.println((binaryFormatLength>=i && binaryFormat.charAt(binaryFormatLength-i)=='1'));
    }

}

public static boolean isBitSet(int number, int position){
    int currPos =1;
    int temp = number;
    while(number!=0 && currPos<= position){
        if(temp%2 == 1 && currPos == position)
            return true;
        else{
            temp = temp/2;
            currPos ++;
        }
    }
    return false;
}

Ausgabe

binaryFormat=1111101000
isBitSet(1000,1)false
false
isBitSet(1000,2)false
false
isBitSet(1000,3)false
false
isBitSet(1000,4)true
true
isBitSet(1000,5)false
false
isBitSet(1000,6)true
true
isBitSet(1000,7)true
true
isBitSet(1000,8)true
true
isBitSet(1000,9)true
true
Kaushik Lele
quelle
2
Eine Division kostet ungefähr hundertmal mehr CPU-Zeit als ein Bitoperator. Und du machst es iterativ. Diese 'Lösung' ist in Bezug auf die Leistung auf der Ebene von BigInteger.
Agoston Horvath
1

Deklarieren Sie ein Temp Int und machen Sie es gleich dem Original. Verschieben Sie dann die Temperatur >> x-mal, sodass sich das zu überprüfende Bit an der letzten Position befindet. Führen Sie dann temp & 0xf aus, um die vorhergehenden Bits zu löschen. Jetzt mit dem letzten Bit verlassen. Schließlich tun Sie, wenn (y & 1 == 0), wenn das letzte Bit eine 1 ist, das gleich 0 sein sollte, sonst gleich 1. Es ist entweder das oder wenn (y + 0x1 == 0) ... nicht zu sicher. herumalbern und sehen


quelle
2
Warum haben Sie eine verschlungene, schwer zu lesende, zweifelhafte Antwort veröffentlicht, die nichts zu den vorhandenen Antworten mit mehr als 50 positiven Stimmen enthält?
Keith Pinson
0

Mein Beitrag - ignoriere den vorherigen

public class TestBits { 

    public static void main(String[] args) { 

        byte bit1 = 0b00000001;     
        byte bit2 = 0b00000010;
        byte bit3 = 0b00000100;
        byte bit4 = 0b00001000;
        byte bit5 = 0b00010000;
        byte bit6 = 0b00100000;
        byte bit7 = 0b01000000;

        byte myValue = 9;                        // any value

        if (((myValue >>> 3) & bit1 ) != 0) {    //  shift 3 to test bit4
            System.out.println(" ON "); 
        }
    } 
}
Miguel Alonso Mosquera
quelle
0

Ich habe eine kleine statische Klasse codiert, die einige der Bitoperationsaufgaben erledigt.

public final class Bitfield {

  private Bitfield() {}

  // ********************************************************************
  // * TEST
  // ********************************************************************

  public static boolean testBit(final int pos, final int bitfield) {
      return (bitfield & (1 << pos)) == (1 << pos);
  }

  public static boolean testNum(final int num, final int bitfield) {
      return (bitfield & num) == num;
  }

  // ********************************************************************
  // * SET
  // ********************************************************************

  public static int setBit(final int pos, final int bitfield) {
     return bitfield | (1 << pos);
  }

  public static int addNum(final int number, final int bitfield) {
      return bitfield | number;
  }

  // ********************************************************************
  // * CLEAR
  // ********************************************************************

  public static int clearBit(final int pos, final int bitfield) {
      return bitfield ^ (1 << pos);
  }

  public static int clearNum(final int num, final int bitfield) {
      return bitfield ^ num;
  }

  }

Wenn Sie Fragen haben, schreiben Sie mir einfach eine E-Mail.

Gute Programmierung!

Alessandro Giusa
quelle
-2

Beseitigen Sie die Bitverschiebung und ihre Komplikationen und verwenden Sie eine LUT für den richtigen andOperanden.

typeseven
quelle
Dies ist erheblich langsamer als eine bitweise Operation. Es würde Adressensuchen über eine bitweise Operation mit 1 oder 2 Taktzyklen erfordern.
Kyle Falconer