Целочисленный логарифм по основанию 2
Вот что я делаю для 64-битных целых чисел без знака. Это вычисляет нижний предел логарифма с основанием 2, который эквивалентен индексу самого старшего бита. Этот метод невероятно быстр для больших чисел, потому что он использует развернутый цикл, который всегда выполняется за log₂64 = 6 шагов.
По сути, он вычитает все более мелкие квадраты в последовательности {0 ≤ k ≤ 5: 2 ^ (2 ^ k)} = {2³², 2¹⁶, 2⁸, 2⁴, 2², 2¹} = {4294967296, 65536, 256 , 16, 4, 2, 1} и суммирует показатели k вычитаемых значений.
int uint64_log2(uint64_t n)
{
#define S(k) if (n >= (UINT64_C(1) << k)) { i += k; n >>= k; }
int i = -(n == 0); S(32); S(16); S(8); S(4); S(2); S(1); return i;
#undef S
}
Обратите внимание, что это возвращает –1, если задан недопустимый ввод 0 (это то, что проверяет начальный -(n == 0)
). Если вы никогда не ожидаете вызвать его с помощью n == 0
, вы можете заменить инициализатор int i = 0;
и добавить assert(n != 0);
при входе в функцию.
Целочисленный логарифм по основанию 10
Целочисленные логарифмы с основанием 10 можно вычислить аналогичным образом - с наибольшим квадратом для проверки, равным 10¹⁶, потому что log₁₀2⁶⁴ ≅ 19,2659 ...
int uint64_log10(uint64_t n)
{
#define S(k, m) if (n >= UINT64_C(m)) { i += k; n /= UINT64_C(m); }
int i = -(n == 0);
S(16,10000000000000000); S(8,100000000); S(4,10000); S(2,100); S(1,10);
return i;
#undef S
}
person
Todd Lehman
schedule
15.07.2014