Java程序实现Schonhage-Strassen算法进行两个数字相乘


Schonhage-Strassen算法在我们需要乘以大十进制数时很有用。由于Java支持1018大小的整数,如果我们需要乘以超过1018位的数字,则需要使用Schonhage-Strassen算法,因为它是最快的乘法算法之一。

它使用两个数字相乘的基本规则。它首先执行线性卷积,然后执行进位以获得最终结果。

问题陈述 - 我们给出了两个大的十进制数mul1和mul2,需要实现Schonhage-Strassen算法来乘以这两个数。

示例

输入

mul1 = 320;  = 760;

输出

243200

解释 - 它将两个数字相乘。

输入

mul1 = 32012233;  = 76031232;

输出

1612188928

解释 - 它将两个大的十进制数相乘。

方法1

在本方法中,我们将首先编写一个函数来计算线性卷积。之后,我们将以一种可以向前进位并添加到下一个元素的方式添加所有线性卷积的结果值。

在这里,我们解释了编写Schonhage-Strassen算法的Java代码的分步算法。

算法

步骤1 - 执行perfromMultiplication()函数。在函数中,首先执行getLinConvolution()函数。

步骤2 - 在getLinConvolution()函数中,使用findTotalDigits()函数计算给定数字的总位数。

步骤2.1 - 在findTotalDigits()函数中,将'cnt'初始化为零以存储数字的总位数。

步骤2.2 - 直到num_int大于零,进行迭代。

步骤2.3 - 在循环中,将num_int除以10。同时,将cnt的值增加1。

步骤2.3 - 最后,返回'cnt'值。

步骤3 - 定义'tmp_mul1'并存储mul1数字的值。另外,定义lcon_len变量以存储数组的长度,我们需要使用该数组来存储线性卷积。

步骤4 - 开始遍历mul2的数字。在循环中,将tmp_mul1的值存储到mul1中,并使用另一个嵌套循环遍历mul1的数字。

步骤5 - 通过将(mul2 % 10) * (mul1 % 10)添加到当前值,更新数组中第(p + q)个索引处的值。

步骤6 - 现在,我们有了线性卷积,需要对列表执行进位。因此,调用addCarry()函数。

步骤7 - 初始化变量以存储乘积、进位和基数。

步骤8 - 开始遍历列表。将'C'添加到列表中第i个索引的值。

步骤9 - 在'predocut_res'中添加B * (linConvoList[i] % 10),其中B是基数。

步骤10 - 将linConvoList除以10,并用它更新'C'的值。

步骤11 - 将基数乘以10。

步骤12 - 所有循环迭代完成后,将C*B添加到乘积结果中,以将最终进位添加到列表中。最后,打印product_res,它是两个十进制数的乘积。

示例

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);
   }
}

输出

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

时间复杂度 - O(M + N),其中M是mul1中的总位数,N是mul2中的总位数。

空间复杂度 - O(M + N),因为存储线性卷积。

在代码中,程序员可以观察到Schonhage-Strassen算法的工作原理与我们在数学中进行的普通乘法相同。程序员可以观察线性卷积的结果来理解算法。

此外,程序员应该尝试编写算法来对两个大数求和,以进行更多练习。

更新于: 2023年8月24日

151 次查看

启动您的职业生涯

通过完成课程获得认证

开始
广告