자주 접하지 못했던 식인 n&-n
에 대해 쓰는 글이다.
n&-n
n
을 음이 아닌 비트 정수라고 하자. 등식 n + (~n) = -1
을 생각하면 -n = ~n + 1
임을 알 수 있다. n&-n
을 평가하기 위해, n
의 이진법 표현에서 자리, 자리, ...에 대한 사례 분석을 진행할 수 있다. n
= 는 의 원소이고, 즉 수와 동시에 비트 문자열이 된다. 비트 에 대해 의 부정을 로 표기하자. 비트 에 대해 는 항상 0이다. 비트 표현에서 숫자의 자리를 명확하게 하기 위해, 0, 1 등 상수 비트의 첨자에 자릿수를 표기한다.
n
이 1으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 여기에 1을 더한-n
의 비트 표현은 이 된다.n&-n
의 비트 표현은 이다. 이를 정수로 읽으면 1이다.n
이 0으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 이전과 달리 여기에 1을 더하면 자리보다 높은 자리에 영향을 주게 된다. 아직 상황이 잘 보이지 않으므로 사례 분석을 좀 더 해보자.n
이 10으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 여기에 1을 더한-n
의 비트 표현은 이고n&-n
의 비트 표현은 이다. 이를 정수로 읽으면 2이다.n
이 00으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 다시, 여기에 1을 더하면 자리보다 높은 자리에 영향을 준다. 다시 사례 분석을 하자.n
이 100으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 여기에 1을 더한-n
의 비트 표현은 이고n&-n
의 비트 표현은 이다. 이를 정수로 읽으면 4이다.n
이 000으로 끝나는 경우, 이고~n
의 비트 표현은 이다. 또 다시, 여기에 1을 더하면 자리보다 높은 자리에 영향을 준다...
계속 사례 분석을 할 수 있지만, 잠시 멈추고 각 사례에서 나타나는 패턴을 분석하자. n
이 1로 끝날 때 n&-n
= 1이고, 10으로 끝날 때 n&-n
= 2이고, 100으로 끝날 때 n&-n
= 4이다. 아직 결과를 확인하지는 않았지만 n
이 1000으로 끝날 때 n&-n
= 8이고, 10000으로 끝날 때 n&-n
= 16이고, n
이
으로 끝날 때 n&-n
= 일 것 같다. 사례 개를 2개의 류로 나누어 다시 사례 분석을 하자.
n
의 비트 표현에서 1이 등장하지 않는 경우,n
=-n
= 0이고n&-n
= 0이다.n
의 비트 표현에서 1이 등장하는 경우, 1이 등장하는 자리수의 집합 (예를 들어 의 경우 )은 자연수의 부분 집합이므로 집합의 최소원이 존재한다. 이를 이라고 하면, 이고,n
은 1과 개의 0으로 끝난다.n
의 비트 표현은 이고,-n
의 비트 표현은 이고n&-n
의 비트 표현은 이다. 이를 정수로 읽으면 , 또는 부호 있는 정수인 경우 일 때 이다.
인 경우 이 읽히는 방법 때문에 n
이 부호 있는 정수인지 부호 없는 정수인지에 따라 분석이 약간 다르게 읽히지만, 일 때는 대체로 같은 분석을 할 수 있다. 모든 경우에 n
↦ n&-n
은 n
의 비트 표현에서 1이 등장할 경우 가장 낮은 자리에 있는 1만을 그 자리와 함께 남기는 연산이다.
활용
PS 고수들은 n+=n&-n
, n-=n&-n
또는 n-=-n&n
과 같은 아름다운 표현을 비트 마스크와 관련된 연산을 하고 싶을 때나 어쩌구 트리에서 인덱스를 계산할 때 종종 사용하는 듯 하다. n&-n
이 무엇인지 알게 되었다면 n
의 이진 표현을 가지고 씨름하거나, n과 비트 and 연산이 0이 아닐 때 까지 2를 곱할 필요 없이 이런 표현이 필요할 때 마음껏 써도 될 듯 하다.