2010-05-23 4 views
2

У меня есть 5-битное целое число, с которым я работаю. Есть ли встроенная функция в Objective-C, которая сообщит мне, какой бит является самым левым?Получение самого последнего бита

i.e. У меня есть 01001, он вернет 8 или позицию.

Благодаря

+0

Вы имеете в виду крайний левый бит, который является 1? Это похоже на ваш пример, но ... –

ответ

4
NSInteger value = 9; 
NSInteger shift = 1; 
for(NSInteger bit = value; bit > 1; bit = value >> ++shift); 
NSInteger leftmostbit = 1 << shift; 

Работы для каждого количества бит.

+3

Не используйте для этого 'pow'. Там нет языковой гарантии, что 'pow' будет доставлять точную мощность в два раза (это происходит в OS X, что, вероятно, является тем, на что нацеливается, поскольку вопрос помечен как« цель-c », но это не переносное предположение). Это также крайне неэффективно на многих платформах. Вы хотите 'leftmostbit = 1 << shift'. –

+0

Спасибо, ты прав. Я обновил код на основе вашего комментария. – Joost

7

Вы можете построить таблицу поиска, с 32 элементами: 0, 1, 2, 2, 3 и т.д.

+0

32-элементная таблица поиска - это лучшее решение для этого конкретного случая. –

+0

Даже таблица из 256 элементов хорошо, для 8-битных целых чисел. – ChrisW

+1

@Stephen: только если вы на 100% уверены, что количество бит будет ** всегда ** быть 5 (или, по крайней мере, относительно небольшим числом), и что вы никогда не хотите делать каких-либо оптимизаций, например. SIMD или GPGPU. –

6

Это фактически ту же операцию, что он рассчитывает число ведущих 0s. Некоторые CPU имеют инструкцию для этого, иначе вы можете использовать трюки, например, найденные в Hacker's Delight.

Он также эквивалентен округлению до ближайшей мощности 2, и снова вы можете найти эффективные методы для этого в Hacker's Delight, например.

uint8_t flp2(uint8_t x) 
{ 
    x = x | (x >> 1); 
    x = x | (x >> 2); 
    x = x | (x >> 4); 
    return x - (x >> 1); 
} 

Смотрите также: Previous power of 2

+1

Это требует двух upvotes. – Joshua

+1

'x | = x >> 1' будет делать. Отличное решение! – Joost

0

Если вы имеете в виду значение любой бит в положении пять из справа («крайний левый» в пять-битное значение), то:

int value = 17; 
    int bit = (value >> 4) & 1; // bit is 1 

Если вы имеете в виду положение левого бита то есть 1:

int value = 2; 
    int position; 
    for (position = 0; position < 5; position++) { 
      int bit = (value >> position) & 1; 
      if (bit == 1) 
        break; 
    } 
    // position is 1 

Позиция будет 0 для бита дальше всего справа, 4 для левого бита ваших пять-битного значения, или 5, если все биты где ноля.

Примечание: это не самое эффективное решение в цикле часов. Надеюсь, это достаточно ясный и образовательный. :)

0

Я не знаю, Objective C, но это, как я хотел бы сделать это в C.

Pow (2, внутр (log2 (номер))

Это должно дать вам немного самый левый 1 . значение

СМ КОММЕНТАРИЙ Стивеном КОРПОРАЦИИ CANON нИЖЕ ПЕРЕД ИСПОЛЬЗОВАНИЕМ РЕШЕНИЯ

+1

Это невероятно медленно на многих платформах и даст вам неправильный ответ на других (нет гарантии, что функции 'log2' или' pow' правильно округлены - даже для небольших целых чисел - и на многих платформах они не являются). –

+0

@ Stephen Canon - я просто хотел показать еще один метод решения этой проблемы. Возможно, вы правы на медленной проблеме, но вся идея создания каста - избавиться от части дроби, и как только вы это сделаете, pow() всегда вернет вам целые числа. Я не знаю, что log2 и pow имеют проблемы округления. Если это так, то результаты могут пойти не так. – naivnomore

+0

Нет гарантии, что 'pow (2, someInteger)' всегда будет возвращать целое число. Фактически, у меня было несчастье использовать несколько платформ, на которых это не было (несчастливо, но верно). –

0

Чтобы очистить все биты ниже значащего бита:.

while (x & (x-1)) x &= x - 1; 
// 01001 => 01000 

Чтобы очистить все биты выше наименьшего значащего бита:

x &= -x; 
// 01001 => 00001 

Чтобы получить положение только установленный бит в байте:

position = ((0x56374210>>(((((x)&-(x))*0x17)>>3)&0x1C))&0x07); 
// 01000 => 3 

В libkern.h есть clz функция, заданная для подсчета ведущих нулей в 32-битном int. Это самая близкая вещь для встроенной функции Objective-C.Для того, чтобы получить позицию самого старшего бита в междунар:

position = 31 - clz(x); 
// 01001 => 3 
2

Если вы не хотите использовать табличный, я хотел бы использовать 31 - __builtin_clz(yourNumber).

__builtin_clz() является встроенным компилятором, поддерживаемым gcc, llvm-gcc и clang (и, возможно, другими компиляторами). Он возвращает число начальных нулевых бит в аргументе integer. Вычитая, что от 31 задает позицию бита старшего разряда. Он должен генерировать достаточно быстрый код для любой целевой архитектуры.

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