Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Karatsuba Algorithm for Fast Multiplication of Large Decimal Numbers Represented as Strings
We are not able to store the large decimal numbers in normal data types such as the int or even in long long, so we store them in the string. When we multiply two integers represented in the form of a string it takes a lot of time more specifically N*M where N is the size of the given string. In this article, we will implement Karatsuba Algorithm for the fast Multiplication of large decimal numbers represented as strings.
Input
string num1 = "34984" string num2 = "937488"
Output
32797080192
Explanation
We will see the algorithm for the multiplication.
Karatsuba Algorithm
According to this algorithm, we are going to make both the strings of the same length (by adding some extra zeros in the front of the smallest number) and we need the length of both the strings of even size, so if large size string is not of even length, then we can add one extra zero in front of it.
Now, we can break both numbers as:
$\mathrm{N_{1}=10^{N/2}*Nl_{1}+Nr_{1}}$here Nl1 represents the first n/2 digits of the given number and NR1 represents the last n/2 digits of the given number, means we have divided the current number into two equal parts.
For example: 1234 can be written as $(\mathrm{12\:*10^2\:+\:34})$.
Similarly, the second number is written as:
$\mathrm{N_{2}=10^{N/2}*Nl_{2}+Nr_{2}}$
Now, the product of these two numbers is:
$\mathrm{=>N_{1}*N_{2}=(10^{n/2}*Nl_{1}+Nr_{1})*(10^{n/2}*Nl_{2}+Nr_{2})}$
$\mathrm{=(10^{n}*Nl_{1}*Nl_{2})+10^{n/2}((Nl_{2}*Nr_{1})+(Nl_{1}*Nr_{2}))+(Nr_{2}*Nr_{1})}$
$\mathrm{=>(Nl_{2}*Nr_{1})+(Nl_{1}*Nr_{2})}$ can be written as
$\mathrm{=(Nl_{1}*Nr_{1})*(Nl_{2}*Nr_{2})-(Nl_{1}*Nr_{1})-(Nl_{2}*Nr_{2})}$
So, our final equation is:
$\mathrm{=>N_{1}*N_{2}=(10^{n}*Nl_{1}*Nl_{2})+(Nr_2*Nr_1)+10^{n/2}((Nl_{1}*Nr_{1})*(Nl_{2}*Nr_{2})-(Nl_{1}*Nr_{1})-(Nl_{2}*Nr_{2}))} $
From the above equation, we can see that we have to just make only three multiplications instead of four multiplications we have to just do the three and we have to go recursively which makes the recursive equation in the form of
$$\mathrm{=>T(n)=3T(n/2)+O(n)}$$
Example
#include <bits/stdc++.h>
using namespace std;
// creating a function to get the addition of the integers passed as parameters in the form of the string
string Sum(string str1, string str2){
// for easy processing, making second string greater
if (str1.size() > str2.size()){
swap(str2,str1);
}
string sum = ""; // string to store the sum
int len1 = str1.length(); // variable to get the size of the first string
int len2 = str2.length(); // variable to get the size of the second string
// reversing both strings to get the sum
reverse(str1.begin(), str1.end());
reverse(str2.begin(), str2.end());
int carry = 0; // variable to store the carry
// traversing over the first string
for (int i = 0; i< len1; i++){
int temp = ((str1[i] - '0') + (str2[i] - '0') + carry);
sum.push_back(temp % 10 + '0');
carry = temp / 10;
}
// traversing over the second string
for (int i = len1; i< len2; i++){
int temp = ((str2[i] - '0') + carry);
sum.push_back(temp % 10 + '0');
carry = temp / 10;
}
// if carry is not zero
if (carry){
sum.push_back(carry + '0');
}
// reverse the sum string
reverse(sum.begin(), sum.end());
return sum;
}
// create a function to find the difference between the given numbers
string Diff(string str1, string str2){
string ans = ""; // string to store the answer
// getting length of both the strings
int len1 = str1.length();
int len2 = str2.length();
// reversing both the given strings
reverse(str1.begin(), str1.end());
reverse(str2.begin(), str2.end());
int carry = 0;
// traversing over the second string and subtracting the first string
for (int i = 0; i< len2; i++){
int temp = ((str1[i] - '0') - (str2[i] - '0') - carry);
// if the subtraction value is less than 0 then add 10 into the variable sub and mark the carry as 1
if (temp < 0) {
temp = temp + 10;
carry = 1;
} else{
carry = 0;
}
ans.push_back(temp + '0');
}
// subtracting the carry from the greater number
for (int i = len2; i< len1; i++) {
int temp = ((str1[i] - '0') - carry);
// If the sub value is -ve, then make it positive
if (temp < 0) {
temp = temp + 10;
carry = 1;
} else{
carry = 0;
}
ans.push_back(temp + '0');
}
reverse(ans.begin(), ans.end()); // reversing the ans string
return ans; // Return answer
}
// creating the function for removal of the zeroes
string removeZeros(string s){
// using regex pattern to remove the zeroes
const regex pattern("^0+(?!$)");
s = regex_replace(s, pattern, "");
return s;
}
// creating the function to multiply the given numbers
string multiply(string num1, string num2){
if (num1.length() > num2.length()){
swap(num1,num2); // getting the second string with greater size
}
// getting length of the numbers and making their size equal
int len1 = num1.length(), len2 = num2.length();
while (len2 > len1) {
num1 = "0" + num1;
len1++;
}
// if their size is one implement the base condition
if (len1 == 1) {
// converting to numbers and returning the results
int res = stoi(num1) * stoi(num2);
return to_string(res);
}
// makking length odd for the strings
if (len1 % 2 == 1) {
len1++;
num1 = "0" + num1;
num2 = "0" + num2;
}
// defining different types of strings that are needed according to the equaltion
string N1l, N1r, N2l, N2r;
// finding the values of all the above strings
for (int i = 0; i< len1 / 2; i++){
N1l += num1[i];
N2l += num2[i];
N1r += num1[len1 / 2 + i];
N2r += num2[len1 / 2 + i];
}
// recursively calling to the function, to get the required product getting the value of N1l * N2l
string a = multiply(N1l, N2l);
// getting the value of N1r * N2r
string b = multiply(N1r, N2r);
// gettign the value of the third condition
string c = Diff(multiply(Sum(N1l, N1r), Sum(N2l, N2r)),Sum(a, b));
// Multiply a by 10^len1 by adding zeroes in the end of a
for (int i = 0; i< len1; i++){
a = a + "0";
}
// Multiply b by 10^(len1/2) by adding zeroes in the end of b
for (int i = 0; i< len1 / 2; i++){
c = c + "0";
}
// getting sum of all the given strings
string res = Sum(a, Sum(b, c));
// Remove leading zeroes from the result
res = removeZeros(res);
return res;
}
int main(){
string num1 = "34984";
string num2 = "937488";
// calling the function
cout<<"The multiplication value of the given numbers is "
<<multiply(num1,num2)<<endl;
return 0;
}
Output
The multiplication value of the given numbers is 32797080192
Conclusion
In this tutorial, we have implemented Karatsuba Algorithm for the fast Multiplication of large decimal numbers represented as strings. When we multiply two integers represented in the form of a string it takes a lot of time more specifically N*M where N is the size of the given string. Karatsuba Algorithm takes O(N^(1.59)) time.