нефункциональный оператор на основе одной строки для величины типа int - PullRequest
1 голос
/ 08 октября 2010

Мне было интересно, есть ли способ получить величину целого числа без использования вызовов функций и только с использованием операторов (без управляющих структур).

В случае, если я здесь неправильно использую термин «магнитуда», я имею в виду, в основном, сколько цифр занято. например. 2468 имеет величину 4.

В противном случае, какой самый эффективный способ сделать это? Лучшее, что я могу придумать, это while ( num /= 10 ) mag++;, но мне просто интересно, есть ли какая-то черная магия там, о которой я не знаю.

Решения на языке стилей C предпочтительны (C, C ++, Java, C # и т. Д.)

Ответы [ 2 ]

1 голос
/ 08 октября 2010

Математически вы хотите ⌊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]);
0 голосов
/ 08 октября 2010

Существуют «битовые хаки» постоянного времени для вычисления связанных значений, например, старший бит, установленный в числе. Это аналог, потому что вы хотите найти старшую цифру, которая не являетсянуль.

Однако, поскольку вас интересует значение base-10, и эти методы используют двоичную арифметику, я не уверен, что они могут быть адаптированы.Однако, глядя на то, как они работают, вы можете получить некоторые идеи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...