2013-11-25 2 views
2

Есть ли эффективный способ удалить первый бит числа в C++/Python, если вы не знаете, насколько велика цифра или ее тип данных?Удаление первого бита

Я знаю в Python. Я могу это сделать, получив bin (n), обрезая строку на 1, а затем переработав ее в int, но мне любопытно, есть ли более «математический» способ сделать это ,

например. говорят, что число равно 6, что равно 110 в двоичном формате. Нарезать первый бит и становится 10, или 2.

+0

Что такое «первый бит»? наиболее значимый? наименее значимый? Если вы ничего не знаете о размере номера или его формате, вы, вероятно, полностью уничтожите номер. например удалите самый сиг-фик подписанного числа, и вы просто удалили бит знака. как вы обрабатываете 8-битное число против. 16-битный номер? если это 16 бит, и вы удаляете бит 7, так как вы считали, что это 8-битное число, теперь вы полностью уничтожили это значение. –

+0

Я не знаю, что большинство/наименее значимых средств, но я добавил пример. Я полагаю, что самый левый бит значения 1 является «наиболее значимым», самый правый бит значения 1 является «наименее» значимым – user111373

+0

В C++ вы можете рассмотреть [операции смены битов] (http://www-numi.fnal.gov/offline_software /srt_public_context/WebDocs/Companion/cxx_crib/shift.html). – cm2

ответ

2

Там немного вертел хак для удаления немного в то время, пока только верхний осталось:

def upper_bit(x): 
    while x & (x - 1): 
     x &= x - 1 
    return x 

Теперь вы можете использовать его в качестве маски:

def mask_off(x, mask): 
    return x & ~mask 

>>> mask_off(6, upper_bit(6)) 
2 

Обратите внимание, что это только работает для положительных чисел, из-за безграничной природы Python ints.

+0

Разве это не самый младший бит? –

+0

@GlennTeitelbaum, вы * удаляете * самый старший бит, чтобы оставить младший бит (ы). Это то, о чем просила проблема. –

+0

Извините, пропустил время - да, это то же самое, что и мой ответ –

1

смотрит на 110 (6) десятичного

Наиболее значимые бит 100 (4 десятичных) // - Обратите внимание, что это всегда сила 2

Создать маску: один меньше, чем старший бит равен 011 (3 десятичных)

Маскирования старшего бита, используя побитовый и: 110 & 011 = 10 (2 десятичного)

Вычисляя MSB (старший бит) было обработано здесь и в других местах довольно часто

+0

@mgilson Вы должны найти ближайшую силу два первых ... – catscradle

+0

@catscradle - Да, я просто понял, что (вот почему я удалил свой комментарий) – mgilson

+0

@catscradle, который является MSB (http://stackoverflow.com/questions/9718453/extract-nmost -significant-non-zero-bits-from-int-in-c-without-loops) –

1

Ну, вы могли бы создать цикл, в котором вы бы удвоить некоторую переменную (скажем, х) в каждой итерации, а затем проверить, является ли эта переменная больше вашего. Если это так, разделите его на два и вычтите из своего номера. Например, если ваш номер 11:

-первая итерация: х = 1 < 11, поэтому продолжают

-Второй итерация: х = 2 < 11, поэтому продолжают

-third итерация: х = 4 < 11, так что по-прежнему

-fourth итерации: х = 8 < 11, так что по-прежнему

: итерация пятой х = 16> 11, таким образом разделить на два х: х = 8. Затем вычтите 8 из своего номера и получите ответ:

11-8 = 3.

0

В Python, я бы один из них:

def chop_msb(i): 
    return i >> 1 & i 
print chop_msb(6) 
> 2 
print chop_msb(12) 
> 4 
print chop_msb(32) 
> 0 

def chop_msb2(i): 
    return 2**(i.bit_length()-1)^i 

print chop_msb2(6) 
> 2 
print chop_msb2(12) 
> 4 
print chop_msb2(32) 
> 0 

Объяснение:

  • Первое:

Это в значительной степени делает то же самое, как @ решение Гленна, но он более эффективно вычисляет маску.

  • Второе:

Это операцию XOR старший бит i с i. Вычисление MSB выполняется (в этом случае) путем вычисления 2 в (длина бит i-1).

XOR возвращает все биты, которые установлены либо в первом значении, либо во втором значении, но не в обоих. Это означает, что вы в основном установить MSB 0 в этом случае:

6: 110 XOR 100 = 010 = 2 
12: 1100 XOR 1000 = 0100 = 4 
32: 100000 XOR 100000 = 000000 = 0 
1

Если вы используете компилятор, который поддерживает __builtin_clz, и вы ограничиваете себя к типу, который __builtin_clz поддерживает, вы можете сделать:

unsigned int chopWithBuiltin(unsigned int x) { 
    //get number of leading redundant sign bits, 
    //which is one less than the position of the MSB 
    int msb_idx = __builtin_clz(x); 
    //now make a mask that is all the bits below the MSB 
    int mask = UINT_MAX >> (msb_idx+1); 
    return x & mask; 
} 

Это использует __builtin_clz, который, мы надеемся, сопоставляется с чем-то быстрым в сборке вместо цикла для обнаружения MSB.

Для отрицательных чисел вы можете построить что-то похожее с __builtin_clrsb, но это усложняется.

Смежные вопросы