算法:大整数相乘问题

  给定两个数字作为字符串。这些数字可能非常大(可能不适合int long int int),或许相乘在计算机可能溢出了,所以任务是找到这两个数字的乘积。

1 Input : num1 = 4154  
2         num2 = 51454
3 Output : 213739916 
4 
5 Input :  num1 = 654154154151454545415415454  
6          num2 = 63516561563156316545145146514654 
7 Output : 41549622603955309777243716069997997007620439937711509062916

  我们可以基于数学思想来分解两个大整数的相乘问题

  从输入的第二个数字最后一位开始乘以输入的第一个数字然后,我们将第二个数字的倒数第二位数字与第一个数字相乘,依此类推。将所有这些乘法相加在相加时,将第 i个乘法移位了。

以下解决方案中使用的方法是仅保留一个数组以获取结果。循环遍历所有数字的第一个和第二个数字,并将结果添加到适当的位置。

  1 package algorithm;
  2 
  3 /**
  4  * 大整数相乘问题
  5  */
  6 public class BIgIntMultiply {
  7     /**
  8      * 以字符串的形式输入两个大整数做乘法
  9      *
 10      * @param num1 整数1
 11      * @param num2 整数2
 12      * @return
 13      */
 14     private static String multiply(String num1, String num2) {
 15         int len1 = num1.length();
 16         int len2 = num2.length();
 17         if (len1 == 0 || len2 == 0)
 18             return "0";
 19 
 20         /* 将结果数以相反的顺序保存在数组中 */
 21         int[] result = new int[len1 + len2];
 22 
 23         /* 以下两个索引用于查找结果中的位置(移位) */
 24         int i_n1 = 0;
 25         int i_n2 = 0;
 26 
 27         /* 在num1中从右到左 */
 28         for (int i = len1 - 1; i >= 0; i--) {
 29             /* 临时保存需要进位的数 */
 30             int carry = 0;
 31             int n1 = num1.charAt(i) - '0';
 32 
 33             /* 在num2中每个数字的乘法运算后向左移动位置 */
 34             i_n2 = 0;
 35 
 36             /* 在num2中从右向左移动 */
 37             for (int j = len2 - 1; j >= 0; j--) {
 38                 /* 取第二个数字的当前数字 */
 39                 int n2 = num2.charAt(j) - '0';
 40 
 41                 /* 将当前数字与第一个数字相乘,然后将结果添加到先前存储的结果charAt当前位置 */
 42                 int sum = n1 * n2 + result[i_n1 + i_n2] + carry;
 43 
 44                 /* 用于下一个迭代相加 */
 45                 carry = sum / 10;
 46 
 47                 /* 存储结果 */
 48                 result[i_n1 + i_n2] = sum % 10;
 49 
 50                 i_n2++;
 51             }
 52 
 53             /* 到最后还有进位值则移位放上去 */
 54             if (carry > 0)
 55                 result[i_n1 + i_n2] += carry;
 56 
 57             /* 在num1中的每个数字重复后向左移动位置 */
 58             i_n1++;
 59         }
 60 
 61         /* 忽略最右边的0 */
 62         int i = result.length - 1;
 63         while (i >= 0 && result[i] == 0)
 64             i--;
 65 
 66         /* 如果全部为'0', 表示num1或num2两者之一为'0'或者都为0 */
 67         if (i == -1)
 68             return "0";
 69 
 70         /* 生成结果字符串 */
 71         StringBuilder s = new StringBuilder();
 72         while (i >= 0) {
 73             s.append(result[i--]);
 74         }
 75 
 76         return s.toString();
 77     }
 78 
 79     public static void main(String[] args) {
 80         String str1 = "-1235421415454545454545454544";
 81         String str2 = "-1714546546546545454544548544544545";
 82 
 83         // String str1 = "1234";
 84         // String str2 = "5678";
 85 
 86         if (str1.charAt(0) == '-' &&
 87                 str2.charAt(0) != '-')
 88         {
 89             str1 = str1.substring(1);
 90             System.out.println("-");
 91         }
 92         else if (str1.charAt(0) != '-' &&
 93                 str2.charAt(0) == '-')
 94         {
 95             str2 = str2.substring(1);
 96             System.out.println("-");
 97         }
 98         else if (str1.charAt(0) == '-' &&
 99                 str2.charAt(0) == '-')
100         {
101             str1 = str1.substring(1);
102             str2 = str2.substring(1);
103         }
104         /*
105             result:            2118187521397235888154583183918321221520083884298838480662480
106             copy from console: 2118187521397235888154583183918321221520083884298838480662480
107          */
108         System.out.println(multiply(str1, str2));
109 
110     }
111 }

 

 

Input : num1 = 4154  
        num2 = 51454
Output : 213739916 

Input :  num1 = 654154154151454545415415454  
         num2 = 63516561563156316545145146514654 
Output : 41549622603955309777243716069997997007620439937711509062916

猜你喜欢

转载自www.cnblogs.com/magic-sea/p/12032047.html