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.

Updated on: 11-Jul-2023

207 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements