Представлять числа в двоичной системе, то искать наиболее значащий бит (самый высокий ненулевой бит). Наивно вы можете это сделать, переставив один бит за раз, пока он не станет равным нулю - это было «слишком много». Это в основном подход, который вы пробовали. Быстрее будет бинарный поиск. Для 32-битного целого, сдвиг вправо на 16; если все еще> 0, сдвиг вправо на 8 и т. д. Я уверен, что вы можете понять это здесь.
Пример кода:
typedef unsigned long long int ulli;
ulli floor2(ulli num){
int msb = 8*sizeof(num)/2;
ulli temp = ((ulli)1)<<msb;
while(msb>1){
msb/=2; // using divide for clarity
if(temp>num) temp>>=msb; else temp<<=msb;
}
if (temp>num) temp/=2;
return temp;
}
Я провел несколько тестов этого алгоритма против topBit
, а также метод builtIn
. Цикл с итерациями 10M, генерирующий «длинное» случайное число, занимает 362 мс в моей системе (без оптимизации компилятора). Если цикл включает в себя один из методов расчета, раз увеличиваются следующим образом:
============= total net
builtin: 407 45
binary search: 579 215
topBit: 2295 1933
Встроенный метод, безусловно, самый быстрый с большим отрывом - на самом деле не удивительно! С 64-разрядными номерами topBit в среднем будет нуждаться в 32 циклах (половина бит устанавливается, поэтому пропускается) и бинарные только 5 циклов, поэтому вы ожидаете разницу в скорости 6x; это примерно то, что вы видите. Когда я определяю ulli
как unsigned short
(16 бит), разница во времени составляет около 2x.
Закрыть, но не совсем точно: http://stackoverflow.com/questions/671815/what-is-the-fastest-most-efficient-way-to-find-the-highest-set-bit-msb- in-an-i –
Возможно, вам стоит взглянуть на [Три рекомендации по оптимизации для C++] Андрея Александреску (http://isocpp.org/blog/2012/12/three-optimization-tips-alexandrescu), где он использует по существу это проблема как пример. Слайд: 24, видео: ~ 30: 00. –
Посмотрите на этот бесплатный код для поиска 'ceil (log2 (x))': http://stackoverflow.com/a/15327567/1553090 - возможно, вы сможете его адаптировать. – paddy