От Шона Андерсона Бит Тиддлинг Хаки :
Найти целочисленную логарифмическую базу 10 от целого числа
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
int r; // result goes here
int t; // temporary
static unsigned int const PowersOf10[] =
{1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)
r = t - (v < PowersOf10[t]);
Целочисленная логарифмическая основа 10 вычисляется как
сначала используя один из методов
выше для поиска базы журнала 2. По
отношение log10 (v) = log2 (v) /
log2 (10), нам нужно умножить его на
1 / log2 (10), что примерно
1233/4096 или 1233, за которыми следует право
смещение 12. Нужно добавить одно
потому что IntegerLogBase2 округляет
вниз. Наконец, так как значение t
только приближение, которое может быть выключено
по одному, точное значение находится
вычитая результат v <
PowersOf10 [т].
Этот метод требует еще 6 операций
чем IntegerLogBase2. Это может быть ускорено
вверх (на машинах с быстрой памятью
доступ) путем изменения базы журнала 2
метод поиска в таблице выше, так что
записи содержат то, что рассчитывается для т
(то есть, предварительно добавить, -mulitply, и
-сдвиг). Для этого потребуется всего 9 операций, чтобы найти
логарифм 10, при условии, что 4 таблицы
используется (по одному на каждый байт v).
Что касается вычисления IntegerLogBase2, на этой странице представлено несколько альтернатив. Это отличный справочник для всех видов высокооптимизированных целочисленных операций.
Также имеется вариант вашей версии, за исключением того, что предполагается, что значения (а не логарифмическая база 10 значений) распределены равномерно, и, следовательно, выполняется экспоненциально упорядоченный поиск:
Найти целочисленное логарифмическое основание 10 целого числа очевидным образом
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
int r; // result goes here
r = (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
Этот метод хорошо работает, когда ввод
равномерно распределен по 32-битным
значения, потому что 76% входов
поймал первое сравнение, 21%
поймал второе сравнение, 2%
пойман третьим и тд
(рубить оставшиеся на 90%
с каждым сравнением). В следствии,
требуется менее 2,6 операций на
средний.