Я пытаюсь использовать C #, чтобы найти индекс первого 1 (справа налево) в двоичном представлении числа. Например, поскольку 100 в двоичном виде это:
0b1100100
Первый 1 находится в третьей позиции справа, поэтому он должен дать 3.
234 должен дать 2, 0 должен дать 0 и т. Д.
Вот мое текущее решение:
k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;
Любые способы, которыми я могу сделать это короче?
Convert.ToString(k,2).IndexOf("1")
это то, что вы хотите, или что-то подобное, хотя неправильный сайт.Ответы:
Если бы только C # поддерживал машинно-специфичные встроенные функции ... Существует одна инструкция, которая может сделать это на языке ассемблера x86, а также на большинстве других процессорных архитектур. Тогда у вас будет не только самый короткий код, но, скорее всего, самый быстрый.
На самом деле, сделать этот код короче - чрезвычайно скучная проблема по сравнению с быстрым созданием этого кода . Существуют всевозможные действительно аккуратные, эффективные решения с небольшим разбросом, и вы также можете рассмотреть возможность использования справочной таблицы.
Все это не имеет значения для игры в гольф. Мне кажется, что ваше текущее решение - лучшее, что вы можете сделать. Конечно, вы можете удалить лишние пробелы:
Я бы лично написал это как:
потому что я думаю, что немного яснее иметь направление условного теста таким образом, а также сравнивать его с нулем, но я предполагаю, что это шесть в одну сторону, полдюжины в другую.
C # не поддерживают неявное преобразование от
int
до ,bool
как C и C ++ сделать, так что вы не можете реально сократить условный тест дальше.Вы также застряли с явным приведением от
double
(как возвращено myMath.Log
) кint
, поскольку C # не позволит этому произойти неявно. Конечно, это, как правило, хорошо, потому что это указывает на большую проблему с производительностью: повышениеint
до adouble
, вычисление лога adouble
, а затем преобразованиеdouble
результата обратно в aint
будет чрезвычайно медленным, поэтому обычно это что-то что вы хотели бы избежать. Но это те извращения, с которыми вам приходится мириться, играя в гольф-код.Я изначально придумал
(разумеется, для простоты), который избегает логарифмирования и, следовательно, улучшает размер кода и скорость. К сожалению, это не всегда дает правильный ответ, и я предполагаю, что это негибкое требование. :-) В частности, он не работает, если входное значение (
k
) имеет коэффициент 8. Это исправимо, но не без увеличения длины кода по сравнению сMath.Log
версией.источник
Math
должен быть полностью квалифицирован, поэтому ваша другая версия должна быть лучше, хотя я на самом деле не посчитал байты.System.
то оно должно быть короче и правильнее.