Karatsuba alqoritmi
"Daha yaxşı" vurma
Sizdən soruşsaydım ki, neçə edir, necə hesablayardınız? Böyük ehtimal, birinci ədədin hədlərini hər dəfəsində sola sürüşdürməklə bir-bir ikinci ədədin hədlərinə vurardınız. Əlbəttə, burda böyük nöqsan yoxdur, lakin bu üsulun zaman mürəkkəbliyinə baxsaq, olduğunu görərik, çünki bütün hədlər bir-birinə vurulur. Bəs bunu daha sürətli etməyin bir yolu varmı?
Əvvəlcə, gəlin, ədədləri tən ortadan ikiyə parçalayaq və hər bir hissəyə ad verək:
Beləliklə, vurma əməlimiz nəticəsi aşağıdakı kimi olur:
Hələ də 4 vurma əməli yerinə yetiririk, bəs onu artırmaqla azaltmaq olar? Bunun üçün mötərizə daxilindəki ifadəmizi genişləndirək:
Və, nəhayət, ifadəmiz belə olur:
Oxucu sual edə bilər ki, əvvəl 4 vurma əməlimiz var idi, indi isə 5, bəs məqsədimiz onu azaltmaq deyildi? Düzdür, vurma əməlimizin sayı artıb, lakin diqqət yetirsək, görərik ki, və hədləri iki dəfə təkrarlanır və onları ikinci dəfə hesablamağımıza ehtiyac yoxdur, buna görə də vurmaların sayını dörddən üçə endirdiyimizi deyə bilərik. Üsul çox sadə görünsə də, zaman mürəkkəbliyini -ə qədər azalda bilir və yalnız 1960-da sovet alimi Anatoli Karatsuba tərəfindən kəşf edilib və Karatsuba alqoritmi adlanır.
İndi isə yuxarıdakı addımları istənilən uzunluqlu ədədlər üçün ümumiləşdirək. Hesab edək ki, hər iki ədədin rəqəmi var, bu halda ədədi uzunluqlu 2 hissəyə ayıra bilərik. Burada yuxarı yuvarlaqlaşdırmadan istifadə edirik, çünki ayırarkən ədədin heç bir həddi kənarda qalmamalıdır və ədədin uzunluğu -dən kiçik olarsa, asanlıqla ədədin soluna əlavə edərək istənilən uzunluğa çatdıra bilərik. Lakin növbəti abzaslarda və proqram nümunəsində görəcəyiniz kimi aşağı və ya yuxarı yuvarlaqlaşdırmanın, adətən, bir fərqi yoxdur. Bundan sonra işlər sadələşir:
Beləcə, son düsturumuz:
olur.
Diqqət yetirsəniz, görərsiniz ki, parçalanmış hissələr üzərində də () rekursiv olaraq Karatsuba alqoritmini tətbiq etmək olar, ta ki ədədləri vurmaq asanlaşana qədər.
Proqramlaşdırmada tətbiqi
Bildiyimiz kimi, kriptoqrafiyada istifadə olunan sadə ədədlər 384 bit və ya 116 rəqəmə çata bilir. Digər riyazi əməllərin də ağırlığını və vurmanın həddən artıq istifadəsini nəzərə alsaq, adi vurma alqoritminin kriptoqrafiyanı nə qədər yavaşladacağını düşünmək çətin olmaz. Məhz bu səbəbdən müasir kriptoqrafiyada böyük ədədləri vurarkən Karatsuba alqoritmi istifadə edilir.
İndi isə Python-da Karatsuba alqoritminin necə tətbiq edildiyinə baxaq:
def karatsuba(num1: str, num2: str) -> int:
# Vurmaq asandırsa, adi şəkildə vuraq
if len(num1) < 2 or len(num2) < 2:
return int(num1) * int(num2)
n = max(len(num1), len(num2))
n_2 = n // 2
# Ədədləri n uzunluğa tamamlayaq
num1 = num1.zfill(n)
num2 = num2.zfill(n)
# Ədədləri iki hissəyə parçalayaq
a, b = num1[:-n_2], num1[-n_2:]
c, d = num2[:-n_2], num2[-n_2:]
bd = karatsuba(b, d)
ac = karatsuba(a, c)
# a+b
s1 = str(int(a) + int(b))
# c+d
s2 = str(int(c) + int(d))
# (a+b)*(c+d) - ac - bd
z0 = karatsuba(s1, s2) - ac - bd
# Sonda isə ədədi bərpa edirik
return (ac * 10**(2 * n_2)) + (z0 * 10**n_2) + bd
La Fin
Əlqərəz, Karatsuba alqoritmi göstərir ki, bəzən düsturu fərqli şəkildə yazmaq və yaxud ona kiçik bir düzəliş etmək məsələni həll edir. Qaqalar demişkən,
"Nöqtə kiçik də olsa, cümlə bitirir".
Görüşənədək.


