Другой подход (я удивлен, что он здесь не упоминается) состоит в создании таблицы из 256 целых чисел, где каждый элемент в массиве является младшим 1 битом для этого индекса. Затем для каждого байта в целом числе вы смотрите вверх в таблице.
Примерно так (я не потратил время на то, чтобы настроить это, это просто для грубой иллюстрации идеи):
int bitcount(unsigned x)
{
static const unsigned char table[256] = { /* TODO: populate with constants */ };
for (int i=0; i<sizeof(x); ++i, x >>= 8)
{
unsigned char r = table[x & 0xff];
if (r)
return r + i*8; // Found a 1...
}
// All zeroes...
return sizeof(x)*8;
}
Идея некоторых табличных подходов к такой проблеме заключается в том, что операторы if
чего-то стоят с точки зрения прогнозирования ветвлений, поэтому вам следует стремиться к их уменьшению. Это также уменьшает количество битовых сдвигов. Ваш подход делает оператор if
и смещение на бит, а этот - один на байт. (Надеюсь, оптимизатор может развернуть цикл for и не запускать сравнение / переход для этого.) Некоторые из других ответов имеют даже меньше операторов if
, чем этот, но табличный подход прост и понятен. Конечно, вы должны руководствоваться фактическими измерениями, чтобы выяснить, имеет ли это значение.