Задайте диапазон бит в круговом поле бит

71
10

У меня есть бит-поле, состоящее из 64 бит:


long bitfield = 0;

Я могу установить бит для данного индекса следующим образом:


void Set(long index)
{
bitfield |= 1L << (int)(index % 64);
}

то есть. если индекс равен 0, 64, 128,... тогда устанавливается бит 0, если индекс равен 1, 65, 129,... тогда установлен бит 1 и т.д.


Вопрос: заданный индекс и счетчик (или нижний и верхний индекс), как я могу установить биты для всех индексов в этом диапазоне без использования цикла?

спросил(а) 2012-04-06T01:23:00+04:00 8 лет, 5 месяцев назад
1
Решение
79

long SetRangeMask(int lower, int upper)     // 3..7
{
if (! (lower <= upper)) throw new ArgumentException("...");

int size = upper - lower + 1; // 7 - 3 + 1 = 5
if (size >= 64) return -1;
long mask = (1 << size) - 1; // #00100000 - 1 = #000011111
return mask << lower | mask >> -lower; // #00011111 << 3 = #011111000
}

ответил(а) 2012-04-06T01:55:00+04:00 8 лет, 5 месяцев назад
56

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


Реальный простой подход, не считающийся особым случаем или оптимизациями, такими как поднятые вопросы, будет выглядеть так:


 static readonly private long[] maskLUT = new long[64,64] { /* generated */ };

void SetRange(long lobit, long hibit)
{
lobit %= 64;
hibit %= 64;

bitfield |= lobit<hibit? maskLUT[lobit,hibit] : maskLUT[hibit,lobit];
}

Мысли:


    вы можете рассмотреть оптимизацию, которая задана [lobit...hibit], если hibit-lobit >= 64, вы можете сразу установить все биты.


    В связности регионов есть немного мысли, учитывая тот факт, что обе границы могут обернуться (сначала вы обертываете обе границы, или вы обходите lobit, и используйте дельта, чтобы найти hibit из обернутой границы, например, с упомянутой ранее оптимизацией?)


ответил(а) 2012-04-06T01:28:00+04:00 8 лет, 5 месяцев назад
41

Вы можете использовать 2 x -1, чтобы создать маску x бит длиной, затем сдвиньте ее и OR, как показано ниже:


void Set( int index, int count ) {
bitfield |= (long)(Math.Pow( 2, count ) - 1) << ((index-count) % 64);
}

Обновление: Мне нравится думать, что Math.Pow оптимизирует полномочия от двух до левого сдвига, но это может и не быть. В этом случае вы можете получить немного больше производительности, заменив вызов на Math.Pow на соответствующий сдвиг влево:


public void Set( int index, int count ) {
bitfield |= ((2 << count - 1) - 1) << ((index-count) % 64);
}

ответил(а) 2012-04-06T01:30:00+04:00 8 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема