Java: Перевірка, якщо біт довжиною 0 або 1


Відповіді:


180

Я б використав:

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

(Можливо, вам вдасться втекти з меншою кількістю дужок, але я ніколи не пам’ятаю перевагу побітових операцій.)


53
Це залежить від мови. У Java це неправда.
harmanjd

12
Це має бути 1 л, або (1 << 32) закінчується тим самим значенням, що і (1 << 0)
mkb

4
@ThibThib нічого дивного в цьому. Будь ласка, не публікуйте дурну приманку для полум'я проти Java.
amischiefr

12
Цікаво, чи краще ((значення >>> x) & 1)! = 0, бо неважливо, довге чи ні, чи гірше, бо воно менш очевидне.
Том Хоутін - таклін

4
@ArtOfWarfare: Іноді я неправильно вводив ==як =- що призводить до дійсного виразу, що присвоює це значення, а це не те, що я хочу. У Java це заборонено (припускаючи, що це не booleanзмінна). Побітові оператори є частиною Java, і це добре, що IMO. Існує безліч ситуацій, коли потрібні побітові оператори. Там немає необхідності прирівнювати , що з чи не тип вираження умови в while, і ifт.д. повинно бути boolean- що я вважаю , що це повинно бути.
Джон Скіт,

98

Інша альтернатива:

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

40
+1 за використання коду, який зрозумілий майбутнім супровідникам
cherouvim

9
Не дуже хороше рішення, якщо цей код буде часто викликати. Ви замінюєте однорядкову альтернативу однорядковою, і бітові зрушення насправді не такі важкі.
wds

3
Довжина рядка! = Читабельність рядка, wds. Ви можете мати рацію, що попереднє рішення є більш ефективним, але різниця, швидше за все, незначна, особливо якщо testBit () буде вбудовано.
WCWedin

7
Слід зазначити, що це рішення виділяє пам'ять і є набагато менш ефективним, ніж побітові оператори. Так, це часто не має значення, але іноді важливо уникати непотрібних GC та / або неефективного коду (програми для Android, у головному циклі гри тощо).
NateS

6
Відходи ресурсів. Якщо ви не можете довіряти "майбутнім супровідникам" для розуміння бітових операцій, тоді у вас є більша проблема, ніж проблема з людськими ресурсами в проекті. Бітові операції - це не магія. Це частина базового набору навичок програміста.
долмен

15

Цікаво, якщо:

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

  }

.. краще, тому що неважливо, чи величина довга чи ні, або гірша, бо вона менш очевидна.

Tom Hawtin - таклін 7 липня о 14:16


Я думаю, що це краще, тому що існує менший потенціал помилок - і якщо ви вважаєте, що це не очевидно, ви завжди можете витягти тест у відповідну іменовану функцію (boolean isBitSet (довге значення, int x) або близько того)
hjhill

12

Ви також можете використовувати

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

EDIT: різниця між " (value>>x) & 1" та " value & (1<<x)" залежить від поведінки, коли x більше, ніж розмір типу "значення" (32 у вашому випадку).

У цьому конкретному випадку з " (value>>x) & 1" у вас буде знак значення, тоді як ви отримаєте 0 з " value & (1<<x)" (іноді корисно отримати бітовий знак, якщо х занадто великий).

Якщо ви віддаєте перевагу нулю в такому випадку, ви можете скористатися >>>оператором " ", замість цього, якщо " >>"

Отже, " ((value>>>x) & 1) != 0" і " (value & (1<<x)) != 0" повністю рівнозначні


8

Для nth-го LSB (найменш значущий біт) має працювати наступне:

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

8
Це має бути 1 л, або (1 << 32) закінчується тим самим значенням, що і (1 << 0)
mkb



4

У Java наступне чудово працює:

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

valueі xможе бути intабо long(і не потрібно бути однаковим).

Слово обережності для програмістів, що не є Java : попередній вираз працює в Java, оскільки в цій мові оператори зсуву бітів застосовуються лише до 5 (або 6, у випадку long) найнижчих бітів операнда правої сторони. Це неявно перекладає вираз value << (~x & 31)(або value << (~x & 63)якщо valueє long).

Javascript : він також працює в javascript (як і java, застосовуються лише найнижчі 5 бітів рахунку зсуву). У javascript будь- numberякий 32-розрядний.

Зокрема, в C, негативний рахунок зсуву викликає невизначену поведінку, тому цей тест не обов'язково буде працювати (хоча може, залежно від вашої конкретної комбінації компілятора / процесора).


2

Значення біта 2 ^ x є "змінною & (1 << x)"


Як сказав Метт Кейн в однакових рішеннях: Це має бути 1 л, або (1 << 32) закінчується тим самим значенням, що і (1 << 0)
drvdijk

2

Якщо комусь не дуже зручно користуватися порозрядними операторами, то нижче код можна спробувати програмно вирішити це. Є два шляхи.

1) Використовуйте функціональність мови Java, щоб отримати рядок двійкового формату, а потім перевірити символ у певній позиції

2) Продовжуйте ділити на 2 і визначайте значення біта в певному положенні.

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

Вихідні дані

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
Один підрозділ коштує приблизно в сто разів більше процесорного часу, ніж бітовий оператор. І ви робите це ітеративно. Це "рішення" на рівні BigInteger щодо продуктивності.
Агостон Горват

1

оголосити temp int і зрівняти його з оригіналом. потім змініть temp >> x разів, щоб біт, який ви хочете перевірити, знаходився в останньому положенні. потім виконайте temp & 0xf, щоб скинути попередні біти. Тепер залишився останній біт. Нарешті, виконайте if (y & 1 == 0), якщо останній біт дорівнює 1, це має дорівнювати 0, інакше буде дорівнювати 1. Це або те, або if (y + 0x1 == 0) ... не надто впевнене. дуріти і бачити


2
Чому ви опублікували заплутану, важку для читання і недоречну відповідь, яка нічого не містить у існуючих відповідях із 50+ голосами?
Кіт Пінсон,

0

Мій внесок - ігнорувати попередній

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

Я закодував невеликий статичний клас, який виконує деякі операції з бітовими операціями.

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

  }

Якщо є якісь питання, що літають, просто напишіть мені електронного листа.

Гарне програмування!


-2

Усуньте бітшифтинг та його тонкощі та використовуйте LUT для правильного andоперанда.


Це значно повільніше, ніж побітова операція. Це вимагало б пошуку адреси за 1 або 2 тактові цикли побітової операції.
Kyle Falconer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.