Java: Kiểm tra xem một bit là 0 hay 1 trong thời gian dài


Câu trả lời:


180

Tôi muốn sử dụng:

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

(Bạn có thể có ít dấu ngoặc hơn, nhưng tôi không bao giờ nhớ ưu tiên của các phép toán bit.)


53
Điều đó phụ thuộc vào ngôn ngữ. Trong java điều đó không đúng.
harmanjd 07-07-09

12
Đó nên là 1L, hoặc (1 << 32) kết thúc với giá trị tương tự như (1 << 0)
MKB

4
@ThibThib không có gì lạ về nó. Xin đừng đăng mồi lửa chống Java ngu ngốc.
amischiefr

12
Tôi tự hỏi liệu ((value >>> x) & 1)! = 0 tốt hơn vì không quan trọng giá trị có dài hay không, hay nó tệ hơn vì nó ít rõ ràng hơn.
Tom Hawtin - tackline 7/7/09

4
@ArtOfWarfare: Đôi khi tôi đã gõ nhầm ==thành =- dẫn đến một biểu thức hợp lệ chỉ định giá trị đó, đó không phải là điều tôi muốn. Trong Java, điều đó là bất hợp pháp (giả sử nó không phải là một booleanbiến). Các toán tử bitwise là một phần của Java, và đó là một điều tốt IMO. Có rất nhiều trường hợp mà bạn muốn toán tử bitwise. Không cần phải kết hợp điều đó với việc có nên hay không loại biểu thức điều kiện while, ifv.v. boolean- điều mà tôi tin là nên làm.
Jon Skeet

97

Một thay thế khác:

if (BigInteger.valueOf(value).testBit(x)) {
    // ...
}

39
1 cho việc sử dụng mã số đó là dễ hiểu bởi bảo trì trong tương lai
cherouvim

9
Không phải là một giải pháp rất tốt nếu mã này sẽ được gọi thường xuyên. Bạn đang thay thế một thay thế một dòng bằng một thay thế một dòng và sự thay đổi bit thực sự không quá khó.
wds

3
Độ dài của dòng! = Khả năng đọc của dòng, wds. Bạn có thể đúng rằng giải pháp trước đó hiệu quả hơn, nhưng sự khác biệt có thể là nhỏ, đặc biệt nếu testBit () được nội tuyến.
WCWedin

7
Cần lưu ý rằng giải pháp này phân bổ bộ nhớ và kém hiệu quả hơn nhiều so với các toán tử bitwise. Vâng, điều đó thường không quan trọng, nhưng đôi khi điều quan trọng là tránh GC không cần thiết và / hoặc mã không hiệu quả (ứng dụng Android, trong vòng lặp chính của trò chơi, v.v.).
NateS

6
Lãng phí tài nguyên. Nếu bạn không thể tin tưởng vào "những người bảo trì tương lai" để hiểu các hoạt động bit thì bạn có một vấn đề lớn hơn thế với nguồn nhân lực trong dự án. Hoạt động bit không phải là phép thuật. Đây là một phần của bộ kỹ năng cơ bản của một lập trình viên.
dolmen

15

Tôi tự hỏi, nếu:

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

  }

.. tốt hơn vì không quan trọng giá trị có lâu dài hay không, hay xấu hơn vì nó ít rõ ràng hơn.

Tom Hawtin - tackline ngày 7 tháng 7 lúc 14:16


Tôi nghĩ nó tốt hơn vì có ít khả năng xảy ra lỗi hơn - và nếu bạn nghĩ nó không rõ ràng, bạn luôn có thể trích xuất thử nghiệm thành một hàm được đặt tên thích hợp (boolean isBitSet (long value, int x) hoặc hơn)
hjhill

12

Bạn cũng có thể dùng

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

CHỈNH SỬA: sự khác biệt giữa " (value>>x) & 1" và " value & (1<<x)" dựa trên hành vi khi x lớn hơn kích thước của loại "giá trị" (32 trong trường hợp của bạn).

Trong trường hợp cụ thể đó, với " (value>>x) & 1" bạn sẽ có dấu giá trị, trong khi bạn nhận được số 0 với " value & (1<<x)" (đôi khi hữu ích để lấy dấu bit nếu x quá lớn).

Nếu bạn muốn có số 0 trong trường hợp đó, bạn có thể sử dụng >>>toán tử "", thay vào đó nếu " >>"

Vì vậy, " ((value>>>x) & 1) != 0" và " (value & (1<<x)) != 0" hoàn toàn tương đương


8

Đối với nLSB thứ (bit ít quan trọng nhất), những điều sau sẽ hoạt động:

boolean isSet = (value & (1 << n)) != 0;

8
Đó nên là 1L, hoặc (1 << 32) kết thúc với giá trị tương tự như (1 << 0)
MKB



4

Trong Java, các cách sau hoạt động tốt:

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

valuexcó thể là inthoặc long(và không cần giống nhau).

Lời cảnh báo cho các lập trình viên không phải Java : biểu thức trước hoạt động trong Java vì trong ngôn ngữ đó, các toán tử dịch chuyển bit chỉ áp dụng cho 5 (hoặc 6, trong trường hợp long) các bit thấp nhất của toán hạng bên phải. Điều này hoàn toàn dịch biểu thức thành value << (~x & 31)(hoặc value << (~x & 63)nếu valuelong).

Javascript : nó cũng hoạt động trong javascript (giống như java, chỉ áp dụng số lượng dịch chuyển 5 bit thấp nhất). Trong javascript, bất kỳ numberlà 32-bit.

Đặc biệt trong C, số dịch chuyển âm gọi ra hành vi không xác định, vì vậy kiểm tra này sẽ không nhất thiết hoạt động (mặc dù có thể, tùy thuộc vào sự kết hợp cụ thể của trình biên dịch / bộ xử lý của bạn).


2

Giá trị của bit 2 ^ x là "biến & (1 << x)"


Như Matt Kane nói về các giải pháp giống hệt nhau: Đó nên là 1L, hoặc (1 << 32) kết thúc với giá trị tương tự như (1 << 0)
drvdijk

2

Nếu ai đó không cảm thấy thoải mái với các toán tử bitwise, thì mã dưới đây có thể được thử để quyết định theo chương trình. Có hai cách.

1) Sử dụng chức năng ngôn ngữ java để lấy chuỗi định dạng nhị phân và sau đó kiểm tra ký tự ở vị trí cụ thể

2) Tiếp tục chia cho 2 và quyết định giá trị bit ở vị trí nhất định.

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;
}

Đầu ra

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

2
Một bộ phận tốn thời gian CPU hơn một trăm lần so với một toán tử bit. Và bạn làm điều đó lặp đi lặp lại. 'Giải pháp' này ở cấp độ BigInteger về hiệu suất.
Agoston Horvath

1

khai báo một int tạm thời và làm cho nó bằng với bản gốc. sau đó shift temp >> x lần, để bit bạn muốn kiểm tra nằm ở vị trí cuối cùng. sau đó thực hiện tạm thời & 0xf để giảm các bit trước đó. Bây giờ còn lại với chút cuối cùng. Cuối cùng làm if (y & 1 == 0), nếu bit cuối cùng là 1, thì giá trị đó phải bằng 0, còn lại sẽ bằng 1. Điều đó hoặc nếu (y + 0x1 == 0) ... không quá chắc chắn. đánh lừa xung quanh và xem


2
Tại sao bạn lại đăng một câu trả lời phức tạp, khó đọc và không có gì trong các câu trả lời hiện có với hơn 50 lượt ủng hộ?
Keith Pinson

0

Đóng góp của tôi - bỏ qua phần trước

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 "); 
        }
    } 
}

0

Tôi đã viết mã một lớp tĩnh nhỏ đang thực hiện một số công cụ hoạt động bit.

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;
  }

  }

Nếu có một số câu hỏi bay xung quanh, chỉ cần viết cho tôi một email.

Lập trình tốt!


-2

Loại bỏ các bithifting và sự phức tạp của nó và sử dụng LUT cho andtoán hạng phù hợp .


Điều này chậm hơn đáng kể so với hoạt động bitwise. Nó sẽ yêu cầu tra cứu địa chỉ qua hoạt động theo chiều kim bit 1 hoặc 2 chu kỳ đồng hồ.
Kyle Falconer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.