상세 컨텐츠

본문 제목

[진짜 BigFloat 구현하기] 5. 카라슈바 알고리즘으로 곱셈 성능 향상

프로그래밍/Multi precision

by ∫2tdt=t²+c 2014. 3. 11. 23:54

본문



곱셈은 앞서(http://bab2min.tistory.com/405)에서 이미 구현했습니다. 다 좋은데 시간복잡도가 O(n^2)이라 숫자가 커지면 커질수록 너무 느려진다는 단점이 있죠. 하지만 이런 문제를 겪을줄 알았는지 이미 일찍이 수학자들이 여러 가지 빠른 곱셈 알고리즘을 발명해 놓았습니다. 여기에서는 곱셈 알고리즘 중 두번째로 구현이 간단한(그 댓가로 뒤에서 두번째로 빠른) 카라슈바 알고리즘(Karatsuba Algorithm)을 구현해보도록 할것입니다.


카라슈바 알고리즘의 개요는 다음과 같습니다. 2자리수 간의 곱을 계산하려면 일반적인 곱셈법으로는 한 자릿수 곱셈이 총 4번이 필요한데, 카라슈바는 한 자릿수 곱셈을 3번만 하고, 덧셈/뺄셈으로 나머지 부분의 결과를 구해내는 아이디어를 떠올립니다.


(편의상 여러 자리 수를 [a, b, c]와 같은 형태로 표시하도록 하겠습니다.)


[a, b] * [c, d] 를 계산하면 [ac, ad bc, bd]의 결과가 나와야 하는거지요.

이를 위해서는 ac, ad, bc, bd를 구해야하므로 총 4번의 곱셈이 필요합니다.

하지만 ad bc = (a b)(c d) - ac - bd 라는것에 주목!

ac, bd는 원래 구해야하는 값이니깐 기억해두었다가, (a b)(c d)를 계산한뒤 빼주면

ad bc를 구할수 있겠죠. 이렇게 되면 곱셈이 3번으로 줄어들게 됩니다. 그 대신 약간의 덧셈 뺄셈이 들어가게 되겠죠.


이 방법을 사용하면 두 2N자리의 곱셈은 3번의 N자리 곱셈과 약간의 덧뺄셈으로 바뀔수 있겠죠. 마찬가지로 N자리끼리의 곱셈은 N/2자리끼리의 곱셈 3번으로 처리할수 있을 것이구요. 이를 재귀적으로 활용하면 원래는 N^2번의 곱셈이 필요했던 연산을 N^(log3)번의 곱셈으로 계산할수 있게 됩니다!


어떤 알고리즘인지 이해가 되셨다면, 바로 구현으로 들어가봅시다.



예전에 구현했던 곱셈 연산함수입니다.


이 두 함수를 구현한 것은 긴 정수배열을 반으로 잘라서 곱셈에 사용해야하기 때문이죠. 자주 사용하게 될테니, 미리 구현해두었습니다.


실제 카라슈바 알고리즘 구현!



그리고 마무리로 xl_mul 함수를 이렇게 고쳤습니다. 이젠 xl_mul 함수를 호출하면 크기에 따라 적절하게 일반 알고리즘 혹은 카라슈바 알고리즘이 호출되겠죠?


집컴퓨터에서 테스트해보니 K_THRESHOLD는 대략 40~48 정도로 잡는게 적당할듯합니다. 그 정도 크기 이상부터 카라슈바 알고리즘이 더 빨라지게 됩니다. (구현이 썩 좋지는 않은가 봅니다. CPU에 따라 다르지만, 보통 2^320 정도부터는 카라슈바가 더 빠르다고 하는데...)



관련글 더보기

댓글 영역