Java Program to Implement the Schonhage-Strassen Algorithm for Multiplication of Two Numbers


The Schonhage-Strassen algorithm is useful when we need to multiply large decimal numbers. As Java supports the 1018 size of integers, and if we need to multiply the digits of more than 1018, we need to use the Schonhage-Strassen algorithm, as it is one of the fastest multiplication algorithms.

It uses the basic rules for the multiplication of two numbers. It first performs the linear convolution and then performs the carry to get the final result.

Problem statement - We have given mul1 and mul2 large decimal numbers and need to implement the Schonhage-Strassen algorithm to multiply both numbers.

Sample examples

Input

mul1 = 320;  = 760;

Output

243200

Explanation - It has multiplied both numbers.

Input

mul1 = 32012233;  = 76031232;

Output

1612188928

Explanation - It has multiplied two large decimal numbers.

Approach 1

We will first write a function to calculate the linear convolution in this approach. After that, we will add all resultant values of linear convolutions in such a way so that we can forward carry to add into the next element.

Here, we have explained a step-by-step algorithm to write Java code for the Schonhage-Strassen algorithm.

Algorithm

Step 1 - Execute the perfromMultiplication() function. In the function, execute the getLinConvolution() function first.

Step 2 - In the getLinConvolution() function, count the total digits of the given number using the findTotalDigits() function.

Step 2.1 - In the findTotalDigits() function, initialize 'cnt' with zero to store the total digits of the number.

Step 2.2 -Make iterations until num_int is greater than zero.

Step 2.3 - In the loop, divide the num_int by 10. Also, increase the value of cnt by 1.

Step 2.3 - At the end, return the 'cnt' value.

Step 3 - Define 'tmp_mul1' and store the value of the mul1 number. Also, define the lcon_len variable to store the length of the array, which we need to use to store linear convolutions.

Step 4 - Start traversing the digits of mul2. In the loop, store the value of tmp_mul1 to mul1 and use another nested loop to traverse the digits of mul1.

Step 5 - Update the value at (p + q)th index in the array by adding (mul2 % 10) * (mul1 % 10) to the current value.

Step 6 - Now, we have linear convolution and need to perform the carry on the list. So, call the addCarry() function.

Step 7 - Initialize the variables to store product, carry, and base.

Step 8 - Start traversing the list. Add 'C' to the value ith index value in the list.

Step 9 - In the 'predocut_res' add B * (linConvoList[i] % 10), where B is the base value.

Step 10 - Divide linConvoList by 10, and update the value of 'C' with it.

Step 11 - Multiply base with 10.

Step 12 - Once all loop iterations are completed, add C*B into the product result to add the final carry to the list. Finally, print the product_res, a product of two decimal numbers.

Example

import java.io.*;
public class Main {
   // for storing the LinearConvolution
   static int[] linConvoList;
   // to store length of the LinearConvolution
   static int lcon_len;
   // function to count total digits in given number
   static int findTotalDigits(long num_int) {
      // Initial digits
      int cnt = 0;
      // Make iterations until num_int is greater than zero
      while (num_int > 0) {
         num_int /= 10;
         cnt++;
      }
      // return cnt value
      return cnt;
   }
   static void getLinConvolution(long mul1, long mul2) {
      // count digits in mul1
      int mul1Digits = findTotalDigits(mul1);
      // count digits in mul2
      int mul2Digits = findTotalDigits(mul2);
      // to store temporary value of mul1
      long tmp_mul1 = mul1;
      // Initialize the length of the linear convolution
      lcon_len = mul1Digits + mul2Digits - 1;
      // Initialize the list
      linConvoList = new int[lcon_len];
      // Filling the linConvoList array
      for (int p = 0; p < mul2Digits; p++, mul2 /= 10) {
         // Reset the value of mul1 for each iteration of mul2
         mul1 = tmp_mul1;
         for (int q = 0; q < mul1Digits; q++, mul1 /= 10) {
            // multiply digit of mul1 and mul2
            linConvoList[p + q] += (int) ((mul2 % 10) * (mul1 % 10));
         }
      }
      System.out.print("The values stored in the linear convolution array are: ");
      for (int p = lcon_len - 1; p >= 0; p--) {
         System.out.print(linConvoList[p] + " ");
      }
      System.out.println();
   }
   static void addCarry() {
      // initialize product to 0
      long product_res = 0;
      // Initialize variables for carry and base
      int C = 0, B = 1;
      // Traverse the list
      for (int i = 0; i < lcon_len; i++) {
         linConvoList[i] += C;
         // performing operations
         product_res = product_res + (B * (linConvoList[i] % 10));
         // Divide the linConvoList[i] by 10 to get carry
         C = linConvoList[i] / 10;
         // Multiply the base by 10
         B *= 10;
      }
      // Add the final carry if it exists
      product_res += C * B;
      System.out.println("\nThe Product of mul1 and mul2 is: " + product_res+ "\n");
   }
   // Multiplication starts here
   static void performMultiplication(long mul1, long mul2) {
      // To get the LinearConvolution
      getLinConvolution(mul1, mul2);
      // Add carry to the LinearConvolution
      addCarry();
   }
   // Driver method
   public static void main(String[] args) {
      long mul1, mul2;
      // long numbers to multiply
      mul1 = 320;
      mul2 = 760;
      performMultiplication(mul1, mul2);
   }
}

Output

The values stored in the linear convolution array are: 21 32 12 0 0 
The Product of mul1 and mul2 is: 243200

Time complexity - O(M + N), where M is the total number of digits in mul1, and N is the total number of digits in mul2.

Space complexity - O(M + N), as store linear convolutions.

In the code, programmers can observe that the Schonhage-Strassen algorithm works the same as the normal multiplication we do in mathematics. Programmers can observe the result of linear convolutions to understand the algorithm.

Also, programmers should try to write algorithms to sum two large numbers for more practice.

Updated on: 24-Aug-2023

95 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements