上次整理过一篇《怎样实现大整数相加?》的文章,有兴趣的小伙伴可以先看一看。
那么,大整数相乘又是如何实现的呢?
问题:
如果给出两个很大很大的整数,这两个数大到long类型也装不下,比如100位整数,如何求它们的乘积呢?
分析:
我们同样可以像大数加法那样,用“列竖式”的方法来求解。
怎样列出这个乘法竖式呢?以 93281 X 2034 为例,竖式如下:
在程序中,我们可以利用int型数组,把两个大整数按位进行存储,再把数组中的元素像小学竖式那样逐个进行计算。
这个乘法竖式的计算过程可以大体分为两步:
1.整数B的每一个数位和整数A所有数位依次相乘,得到中间结果。
2.所有中间结果相加,得到最终结果。
代码如下:
/**
* 大整数求乘积
* @param bigNumberA 大整数A
* @param bigNumberB 大整数B
*/
public static String multiply(String bigNumberA, String bigNumberB) {
//1.把两个大整数用数组逆序存储,数组长度等于两整数长度之和
int lengthA = bigNumberA.length();
int lengthB = bigNumberB.length();
int[] arrayA = new int[lengthA];
for(int i=0; i< lengthA; i++){
arrayA[i] = bigNumberA.charAt(lengthA-1-i) - '0'; //“ - '0'”是将String型转化为int型
}
int[] arrayB = new int[lengthB];
for(int i=0; i< lengthB; i++){
arrayB[i] = bigNumberB.charAt(lengthB-1-i) - '0';
}
//2.构建result数组,数组长度等于两整数长度之和
int[] result = new int[lengthA+lengthB];
//3.嵌套循环,整数B的每一位依次和整数A的所有数位相乘,并把结果累加
for(int i=0;i<lengthB;i++) {
for(int j=0;j<lengthA;j++) {
//整数B的某一位和整数A的某一位相乘
result[i+j] += arrayB[i]*arrayA[j];
//如果result某一位大于10,则进位,进位数量是该位除以10的商
if(result[i+j] >= 10){
result[i+j+1] += result[i+j]/10; //将进位存储到结果数组的下一位
result[i+j] = result[i+j]%10; //将1位数存储到结果数组对应位
}
}
}
//4.把result数组再次逆序并转成String
StringBuilder sb = new StringBuilder();
//用于标记是否找到大整数的最高有效位
boolean findFirst = false;
for (int i = result.length - 1; i >= 0; i--) { //从后往前
if(!findFirst){
if(result[i] == 0){ //用于跳过结果数组末尾的0
continue;
}
findFirst = true;
}
sb.append(result[i]);
}
return sb.toString();
}
public static void main(String[] args) {
String x = "3338429042340042304302404";
String y = "12303231";
System.out.println(multiply(x, y));
}
时间复杂度:
那么,这个算法的时间复杂的是多少呢?
由于两个大数的所有数位都要彼此一一相乘,如果大整数A的长度为m,大整数B的长度为n,那么时间复杂度就是O(m*n)。
如果两个大数的长度比较接近的话,也可以写为O(n2)。
优化:
可以用分治法或者快速傅立叶变换进行优化,由于太过复杂,这里暂不深入探究。
例题:
阶乘计算:
题解可以参考【蓝桥杯】[基础练习VIP]阶乘计算
本文来源于微信公众号程序员小灰,有删改。