Инновационный способ проверки, если число имеет только один бит в подписанном int - PullRequest
29 голосов
/ 01 июля 2010

Я ищу инновационный способ проверить, есть ли у числа только один в бите в целых числах со знаком.

Мне хорошо известно, что я могу просто сделать цикл со счетчиком, некоторое модульное делениеи немного сдвинуть.Но мне любопытно, есть ли лучший способ, так как мы ищем только ОДИН бит, который будет включен.

bool HasOnlyOneBit (int  numb)
{
   //return true if numb has only one bit (I.E. is equal to 1, 2, 4, 8, 16... Int.MinValue)
}

Ответы [ 6 ]

43 голосов
/ 01 июля 2010
return x == (x & -x);

Этот ответ работает из-за способа обозначения дополнения до двух.

Во-первых, пример.Предположим, у нас есть 8-битные целые числа со знаком.

00010000  =  16
11110000  = -16

Побитовое значение и в результате вы получите 00010000, равное вашему исходному значению!Это работает потому, что при отрицании в дополнении 2 сначала инвертируйте все биты, а затем добавьте 1. У вас будет куча нулей и куча переносов, пока единица не встанет на свое место.Битовая, а затем проверяется, установлен ли правильный бит.

В случае числа, которое не является степенью двойки:

  00101010  =  42
& 11010110  = -42
----------
  00000010 !=  42

Ваш результат все равно будет иметь толькоодин бит, но он не будет соответствовать исходному значению.Поэтому в вашем исходном значении было установлено несколько битов.

Примечание: Этот метод возвращает true для 0, что может быть или не быть желательным.

25 голосов
/ 01 июля 2010

Это известная проблема

(x & x-1) == 0

Мощность 2 из Вики: здесь

64 = 01000000 (x)
63 = 00111111 (x-1)
______________
&  = 00000000  == 0
______________ 

Случай, когда включены некоторые другие биты

18 = 00010010 (x)
17 = 00010001 (x-1)
______________
&  = 00010000  != 0
______________ 
8 голосов
/ 01 июля 2010

Я бы порекомендовал вам взглянуть на страницу Bit Twiddling Hacks и выбрать наиболее подходящий вариант в разделе " Определение, является ли целое число степенью 2 " или " Установлен счетный бит".

2 голосов
/ 01 июля 2010

return (x && ((x & x-1) == 0))

1 голос
/ 11 мая 2015
return (x && (0x8000000000000000ULL % x));

Это упрощение следующего кода:

if (x == 0) {
    return false;
} else if (0x8000000000000000ULL % x) {
    return false;
} else {
    return true;
}

Объяснение: 0x8000000000000000 - самое высокое значение "только 1 бит" для 64-битного регистра. Только деление на другое значение «только 1 бит» не приведет к остатку.

0 голосов
/ 01 июля 2010

Перенести журнал в базу 2 вашего номера, если это целое число, то ваш номер имеет только 1 1 бит. Не уверен, что я думаю, что это лучше, чем любой из ваших исключенных вариантов.

...