Home

Реклама

Настроить

Битхак

Что это?
(u ^ (u | (u-1))) + 1


UPD: [info]renatm первым указал, что этот код (4 команды) оставляет в числе установленным только младший единичный бит, [info]dfyz вспомнил более короткий (3 команды) вариант:
u & ~(u-1)
а [info]arti_kz еще более короткий (тоже 3 команды):
u & -u

Интересно сравнить их ассемблерный код и скорость выполнения 1730000000 итераций в цикле (примерно такова тактовая частота моего процессора):

(u ^ (u | (u-1))) + 1lea edx, [eax-1]
or edx, eax
xor edx, eax
inc edx
2953ms
u ^ (u | (u-1))lea edx, [eax-1]
or edx, eax
xor edx, eax
2263ms
u & ~(u-1)lea edx, [eax-1]
not edx
and edx, eax
1965ms
u & -umov edx, eax
neg edx
and edx, eax
1916ms


До чего техника дошла! ©

На самом деле, конечно, компилятор частично раскрывает циклы, что позволяет процессору эффективно параллелить вычисления.

Comments

младший бит?
Это младший бит. Не знаю, зачем нужны такие задачки, но определённого сорта люди очень их любят. Мне кажется, это те же самые люди, которые считают что джава тормозит, а комментарии и юниттесты - для тупых.
Тожп не знаю — случайно придумалось. «Жава не тормозит». Юнит-тесты — для неуверенных :)
не проще u & -u ?
Проще.
~(n-1) и -n - одно и то же.
Конечно.
А почему не просто u&1 ? Простые пути не для умных?
Нелюбовь к непосредственным операндам?
Поправил: младший единичный бит.

а разница?

Мнэ... И что?

Re: а разница?

110100 - (u & -u) -> 000100
110100 - (u & 1) -> 000000

Re: а разница?

Понял :)
Лучше тогда писать "младший ненулевой бит"
кстати, а u&1 процессор быстрее выполнит ?
мне кажется, что да, но об`яснить не могу :)
Вообще, не факт. На многих машинах загрузка непосредственного операнда выполняется медленно (скажем, два такта против одного в случае загрузки с указанного адреса). Так, простое присваивание x = 0 выполняется дольше, чем XOR с самим собой x ^= x. Но в программах такие ухищрения обычно не используются, поскольку понятность кода всё же снижается, а эффективность... Вне цикла не важно, а внутри цикла легко лечится выделением временной регистровой переменной. Причём, лечением занимается сам компилятор. :)

Реклама

Настроить