演算法系列之九 Karatsuba快速相乘演算法

2021-09-02 09:38:32 字數 4822 閱讀 9894

【概述】

karatsuba乘法是一種快速乘法。此演算法在2023年由anatolii alexeevitch karatsuba 提出,並於2023年得以發表。

此演算法主要用於兩個大數相乘。普通乘法

的複雜度是n

2,而karatsuba演算法的複雜度僅為3nlog3

≈3n1.585

(log3是以2為底的)

【步驟】

karatsuba演算法主要應用於兩個大數的相乘,原理是將大數分成兩段後變成較小的數字,然後做3次乘法,並附帶少量的加法操作和移位操作。

現有兩個大數,x,y。

首先將x,y分別拆開成為兩部分,可得x1,x0,y1,y0。他們的關係如下:

x = x1 * 10

m + x0;

y = y1 * 10m + y0。其中m為正整數,m < n,且x0,y0 小於 10m。

那麼xy = (x1 * 10m + x0)(y1 * 10m + y0)

=z2 * 10

2m + z1 * 10m + z0,其中:

z2 = x1 * y1;

z1 = x1 * y0 + x0 * y1;

z0 = x0 * y0。

此步驟共需4次乘法,但是由karatsuba改進以後僅需要3次乘法。因為:

z1 = x1 * y0+ x0 * y1

z1 = (x1 + x0) * (y1 + y0) - x1 * y1 - x0 * y0,

故x0 * y0 便可以由加減法得到。

所以:x*y = z2 * 102m+ z1 * 10m +z0

z2 = x1 * y1

z1 = (x1 + x0) * (y1 + y0) - x1 * y1 - x0 * y0 =(x1 + x0) * (y1 + y0) - x1 * y1 - z0

z0 = x0 * y0

recursively computer (x1*y1)

recursively computer (x1 + x0) * (y1 + y0)

recursively computer (x0 * y0)

【例項講解】

設x = 12345,y=6789,令m=3。那麼有:

12345 = 12 * 1000 + 345;

6789 = 6 * 1000 + 789。

下面計算:

z2 = 12 * 6 = 72;

z0 = 345 * 789 = 272205;

z1 = (12 + 345) * (6 + 789) - z2 - z0 = 11538。

然後我們按照移位公式(xy = z2 * 102m + z1 * 10m+ z0)可得:

xy = 72 * 1000

2 + 11538 * 1000 + 272205 = 83810205。

【偽**】

procedure karatsuba(num1, num2)

if(num1 <

10) or (num2 <10)

return num1*num2

/* calculates the size of the numbers */

m =max(size_base10(num1)

, size_base10(num2)

) m2 = m/

2/* split the digit sequences about the middle */

x1, x0 = split_at(num1, m2)

y1, y0 = split_at(num2, m2)

z0 = karatsuba(x0,y0

) z1 = karatsuba(

(x1+x0),

(y1+y0)

) z2 = karatsuba(x1,y1)

return

(z2*10^

(2*m2))+

((z1-z2-z0)*10

^(m2))+

(z0)

【**】

/*********************************

* 日期:2015-01-29

* 題目: karatsuba快速相乘演算法

* 部落格:

**********************************/

#include #include #include using namespace std;

// given two unequal sized bit strings, converts them to

// same length by adding leading 0s in the smaller string. returns the

// the new length

int makesamelen(string& num1,string& num2)//for

return len2;

}//if

else//for

return len1;

}//else

}// big number minus function

string minusstring(string num1, string num2) //if

// 正負

bool positive = true;

if(len1 < len2 || (len1 == len2 && num1 < num2))//if

string result;

int i = len1 - 1,j = len2 - 1;

int a,b,sum,carray = 0;

// 從低位到高位對位做減法

while(i >= 0 || j >= 0)//if

result.insert(result.begin(),sum + '0');

--i;

--j;

}//while

// 刪除前導0

string::iterator it = result.begin();

while(it != result.end() && *it == '0')//while

result.erase(result.begin(),it);

return positive ? result : "-"+result;

}// big number add function

string addstring(string num1,string num2)//if

if(len2 <= 0)

string result;

int i = len1-1,j = len2-1;

int a,b,sum,carry = 0;

// 倒序相加

while(i >= 0 || j >= 0 || carry > 0)//while

return result;

}// 移位

string shiftstring(string num,int len)//if

for(int i = 0;i < len;++i)//for

return num;

}// karatsuba快速相乘演算法

string karatsubamultiply(string num1, string num2) //if

// all digit are one

if(len == 1)//if

int mid = len / 2;

// find the first half and second half of first string.

string x1 = num1.substr(0,mid);

string x0 = num1.substr(mid,len - mid);

// find the first half and second half of second string

string y1 = num2.substr(0,mid);

string y0 = num2.substr(mid,len - mid);

// recursively computer

string z0 = karatsubamultiply(x0,y0);

string z1 = karatsubamultiply(addstring(x1,x0),addstring(y1,y0));

string z2 = karatsubamultiply(x1,y1);

// (z2*10^(2*m))+((z1-z2-z0)*10^(m))+(z0)

// z2*10^(2*m)

string r1 = shiftstring(z2,2*(len - mid));

// (z1-z2-z0)*10^(m)

string r2 = shiftstring(minusstring(minusstring(z1,z2),z0),len - mid);

return addstring(addstring(r1,r2),z0);

}int main(){

string num1("12345001");

string num2("1006789");

string result = karatsubamultiply(num1,num2);

// 輸出

cout<

九章演算法系列(一)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!問題 實現乙個memcpy函式 本題主要考慮兩點 1 記憶體重疊與否2 重疊記憶體的copy方式 無重疊的記憶體copy void mymemcpy void dst,const void src,size t num if des src num...

C 演算法系列之排序

插入排序 o n2 基本思路就是玩撲克牌的時候,從牌堆裡摸牌放到手上的思路 include include include include include include const int m 1000 const int n 1000 template void insertsort const...

經典演算法系列之 遞迴

1 前言 演算法,在計算機中的地位,就相當於人類大腦的決策中樞系統,哪怕最簡單的演算法,其精妙的思維方式,都可以讓人開啟一扇新的視窗。演算法,它不僅僅只是狹義的用來解決電腦科學領域的問題,更是一種 思維方式 演算法思維,是一種深度思考和創造的過程。演算法,只有真正理解了,而不只是所謂的知道,並將應用...