Математически вы хотите ⌊log 10 (| x |) ⌋ + 1. Если x не равно 0.
Разница между оператором и функцией, которую вы задаете, довольно произвольна.Всегда можно создать язык с оператором ⌊log 10 (| x |) ⌋ + 1!
Тем не менее, для удовольствия, мы можем начать с создания целочисленного журнала 10 (x) метод, который легче всего сделать с помощью простого сравнения:
//assumes 32-bit int in max value. Add cases accordingly
return (x >= 1000000000) ? 9 : (x >= 100000000) ? 8 : (x >= 10000000) ? 7 :
(x >= 1000000) ? 6 : (x >= 100000) ? 5 : (x >= 10000) ? 4 :
(x >= 1000) ? 3 : (x >= 100) ? 2 : (x >= 10) ? 1 : 0;
Мы собираемся добавить 1 к любому полученному результату, поэтому нам даже не нужно это дополнение,мы просто изменим наш результат:
return (x >= 1000000000) ? 10 : (x >= 100000000) ? 9 : (x >= 10000000) ? 8 :
(x >= 1000000) ? 7 : (x >= 100000) ? 6 : (x >= 10000) ? 5 :
(x >= 1000) ? 4 : (x >= 100) ? 3 : (x >= 10) ? 2 : 1;
Бонус в том, что это также правильно обрабатывает случай x == 0.
Теперь нам просто нужно абсбить его.
x = x > 0 ? x : -x;
return (x >= 1000000000) ? 10 : (x >= 100000000) ? 9 : (x >= 10000000) ? 8 :
(x >= 1000000) ? 7 : (x >= 100000) ? 6 : (x >= 10000) ? 5 :
(x >= 1000) ? 4 : (x >= 100) ? 3 : (x >= 10) ? 2 : 1;
А для однострочника это:
return ((x > 0 ? x : -x) >= 1000000000) ? 10 : ((x > 0 ? x : -x) >= 100000000) ? 9 : ((x > 0 ? x : -x) >= 10000000) ? 8 : ((x > 0 ? x : -x) >= 1000000) ? 7 : ((x > 0 ? x : -x) >= 100000) ? 6 : ((x > 0 ? x : -x) >= 10000) ? 5 : ((x > 0 ? x : -x) >= 1000) ? 4 : ((x > 0 ? x : -x) >= 100) ? 3 : ((x > 0 ? x : -x) >= 10) ? 2 : 1;
Проблема в том, считаете ли вы ?:
управляющей структурой или нет.Он является оператором, но он выполняет ветвление (и имеет более реальное влияние, чем то, используется ли управляющая структура, хотя все еще остается микро-от него избавиться).
Не ветвлениепо крайней мере, должно быть возможно в многолинейном режиме, давайте посмотрим.
Не разветвляющийся абс - это просто:
(x ^ (x >> 31)) - (x >> 31); // assuming 32-bit int, adjust shift accordingly
Теперь для логарифма я обманываю и смотрю немного путаницыхаки я не помнюЯ просто собираюсь сделать сухой перенос кода (поскольку я до сих пор занимался C # и могу придерживаться его) из того, что я могу прочитать по http://graphics.stanford.edu/~seander/bithacks.html,, и оставить тестирование и исправление любых ошибок, которые у меня есть.введено в качестве упражнения:
Мы начнем с поиска лога 2 (x);
int[] MultiplyDeBruijnBitPosition = new int[]
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
int l = x >> 1; // first round down to one less than a power of 2
l |= l >> 2;
l |= l >> 4;
l |= l >> 8;
l |= l >> 16;
l = MultiplyDeBruijnBitPosition[(uint)(l * 0x07C4ACDDU) >> 27];
Теперь мы можем использовать это, чтобы найти логарифм с основанием-10:
int[] PowersOf10 = new int[]
{1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
int t = (l + 1) * 1233 >> 12;
return t - (x < PowersOf10[t]);