문제해결자체재수강 중 거듭제곱을 빠르게 계산하는 방법에 대해 교수님이 짧게 언급을 하셔서 따로 더 찾아서 공부를 해보았다.
을 계산하는 가장 쉬운 방법은 를 번 곱하는 이 걸리는 방식이다.
그러나 지금부터 설명할 방법은 에 거듭제곱 계산이 가능하다.
가령, 의 지수를 이진수로 표현하면 이다. 그리고 이걸 다시쓰면, 이고, 은 비트연산으로 세번만에 구해낼 수 있다. 밑을 포함하여 다시 써보면, 이다.
을 계산하기 위해 과 을 구하고 이 둘을 곱해보자.
실제 거듭제곱 계산 결과(과 )를 표시할 변수 a는 3, 지수를 표시할 변수 n은 9, 최종 결과값을 담게될 변수 res는 1로 초기화한다.
int a = 3, n = 9; int res = 1;
우리가 갖고 있는 변수 a를 계속 제곱하면,
while (...) { ... a *= a; }
그리고 위 a를 언제 res에 곱해야 할까 생각해보면,
과일 때 즉, 지수가 1000, 0001일때다.
변수 n을 오른쪽 쉬프트로 컨트롤하면서 1과 bitwise AND연산을 수행하면 우리가 원하는 때에만 res에 a값을 곱해줄 수 있다.while (n > 0) { if ((n & 1) != 0) res *= a; a *= a; n >>= 1; }
#1) a=인 상황, 1001&1==1!=0이므로 res가 3으로 업데이트 된다. (을 곱해준 격)
#2) a=인 상황, 100&1==0이므로 if문 실행 안됨. (은 곱해주지 않은 격)
#3) a=인 상황, 10&1==0이므로 if문 실행 안됨. (은 곱해주지 않은 격)
#4) a=인 상황, 1&1==1!=0이므로 res가 으로 업데이트 된다. (을 곱해준 격)
#include <stdio.h>
int func(int a, int n);
int main()
{
int a = 3, n = 9;
printf("%d\n", func(a, n));
return 0;
}
int func(int a, int n)
{
int res = 1;
while (n > 0)
{
if ((n & 1) != 0) res *= a;
a *= a;
n >>= 1;
}
return res;
}