정수 제곱근 구하기

Posted by 적분 ∫2tdt=t²+c
2012.10.11 03:10 프로그래밍/테크닉

가끔씩 정수의 제곱근을 구해야할 경우가 가끔씩 있는데, 이때 가장 편한 해결책은 float로 캐스팅해서 sqrt()함수에 넣은뒤 다시 int로 캐스팅하는 것입니다. 요즘 CPU들은 워낙 좋아서 부동소수점 제곱근 연산은 뚝딱 해치우니 속도 걱정은 할 필요가 없지요. 다만... 부동소수점 연산이 잘 지원안되는 환경에서 코딩을 하는 경우에는 정수 제곱근을 구하기위해 선뜻 sqrt함수를 쓰기가 꺼려집니다. 그래서 간단한 연산을 통해 정수 제곱근을 구해내는 함수를 구현해보도록 하겠습니다.




정수 제곱근을 구해주는 isqrt 함수입니다.구현원리는 정말 단순합니다. 어떤 정수 n으로부터 차례대로 1, 3, 5, 7, 9 ...를 빼가면, 그 빼간 횟수가 n의 정수 제곱근이 됩니다.



근데 이건 반복횟수가에 비례해서 증가하기에, 그다지 효율적인 구현이라고는 보기 힘들군요. 약간 최적화해봅시다. 입력된 n이 k비트 정수라고 가정하면, 당연히 n의 제곱근은 k/2비트가 될겁니다. 이걸 이용하면, 반복횟수를 확실히 줄일수 있을듯 한데요?



의도치 않게 코드가 길어졌는데, 위의 bit8과 bit32는 정수가 몇 비트짜리 정수인지 구하기 위한 함수입니다. (기억이 가물가물한데 아마 저 역할을 해주는 어셈블리 연산자가 있었던거 같은데... 찾기 귀찮아서 그냥 함수를 구현해버렸긔ㅋ...) 최적화된 isqrt2함수는 비트수를 이용해 제곱근을 근사해서 i를 설정하고, 거기서부터 차례대로 홀수를 빼나가서 반복횟수를 줄였습니다.


아 최적화를 했으면 성능 비교를 해봐야겠지요.

isqrt함수와 isqrt2함수를 임의의 int 정수 500만개에 대해 수행해보았습니다. (/O2옵션주고 컴파일)

제 컴퓨터의 결과는 isqrt는 890ms, isqrt2는 390ms로 60%에 가까운 속도향상을 보이는군요 훗훗.

Tags
이 댓글을 비밀 댓글로