C # Первый 1 (справа налево) в двоичном числе


10

Я пытаюсь использовать C #, чтобы найти индекс первого 1 (справа налево) в двоичном представлении числа. Например, поскольку 100 в двоичном виде это:

0b1100100

Первый 1 находится в третьей позиции справа, поэтому он должен дать 3.

234 должен дать 2, 0 должен дать 0 и т. Д.

Вот мое текущее решение:

k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;

Любые способы, которыми я могу сделать это короче?


1
Очевидный совет - убрать лишние пробелы. Я вижу 10 пробелов, которые вы можете легко удалить.
Джеймс

Convert.ToString(k,2).IndexOf("1")это то, что вы хотите, или что-то подобное, хотя неправильный сайт.
Волшебная урна осьминога

14
@ close-избирателей - Почему закрытые голоса? Я думаю, что это вопрос советов по теме . Или были какие-то изменения правил, которые я пропустил в этом отношении?
Цифровая травма

Ответы:


3

Если бы только C # поддерживал машинно-специфичные встроенные функции ... Существует одна инструкция, которая может сделать это на языке ассемблера x86, а также на большинстве других процессорных архитектур. Тогда у вас будет не только самый короткий код, но, скорее всего, самый быстрый.

На самом деле, сделать этот код короче - чрезвычайно скучная проблема по сравнению с быстрым созданием этого кода . Существуют всевозможные действительно аккуратные, эффективные решения с небольшим разбросом, и вы также можете рассмотреть возможность использования справочной таблицы.

Все это не имеет значения для игры в гольф. Мне кажется, что ваше текущее решение - лучшее, что вы можете сделать. Конечно, вы можете удалить лишние пробелы:

k<1?0:(int)Math.Log(k&-k,2)+1

Я бы лично написал это как:

k>0?(int)Math.Log(k&-k,2)+1:0

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

C # не поддерживают неявное преобразование от intдо , boolкак C и C ++ сделать, так что вы не можете реально сократить условный тест дальше.

Вы также застряли с явным приведением от double(как возвращено my Math.Log) к int, поскольку C # не позволит этому произойти неявно. Конечно, это, как правило, хорошо, потому что это указывает на большую проблему с производительностью: повышение intдо a double, вычисление лога a double, а затем преобразование doubleрезультата обратно в a intбудет чрезвычайно медленным, поэтому обычно это что-то что вы хотели бы избежать. Но это те извращения, с которыми вам приходится мириться, играя в гольф-код.


Я изначально придумал

k > 0
      ? ((k & -k) >> 1) + 1
      : 0

(разумеется, для простоты), который избегает логарифмирования и, следовательно, улучшает размер кода и скорость. К сожалению, это не всегда дает правильный ответ, и я предполагаю, что это негибкое требование. :-) В частности, он не работает, если входное значение ( k) имеет коэффициент 8. Это исправимо, но не без увеличения длины кода по сравнению с Math.Logверсией.


Обратите внимание, что для кода гольф Mathдолжен быть полностью квалифицирован, поэтому ваша другая версия должна быть лучше, хотя я на самом деле не посчитал байты.
TheLethalCoder

Вы имеете в виду тот, который производит неправильный вывод? @the
Коди Грей

Ну, вы сказали, что есть решение, но это сделает его длиннее. Если исправление короче, чем при включении версии OP, System.то оно должно быть короче и правильнее.
TheLethalCoder
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.