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
@ Близькі виборці - Чому закриті голоси? Я думаю, що це питання на тематичні поради . Або були якісь зміни правил, які я пропустив у зв'язку з цим?
Цифрова травма

Відповіді:


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(як повернувся мій Math.Log) int, оскільки C # не дозволить це зробити неявно. Звичайно, це, як правило, добре, тому що це вказує на те, що у вас тут є велика проблема продуктивності: просування intдо а double, обчислення журналу а doubleта перетворення doubleрезультату назад у формат 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.