怎样实现大整数相乘?

上次整理过一篇《怎样实现大整数相加?》的文章,有兴趣的小伙伴可以先看一看。

那么,大整数相乘又是如何实现的呢?

问题:

如果给出两个很大很大的整数,这两个数大到long类型也装不下,比如100位整数,如何求它们的乘积呢?

分析:

我们同样可以像大数加法那样,用“列竖式”的方法来求解。

怎样列出这个乘法竖式呢?以 93281 X 2034 为例,竖式如下:
怎样实现大整数相乘?_第1张图片
在程序中,我们可以利用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= 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)。

优化:

可以用分治法或者快速傅立叶变换进行优化,由于太过复杂,这里暂不深入探究。

例题:

阶乘计算:
怎样实现大整数相乘?_第2张图片
题解可以参考【蓝桥杯】[基础练习VIP]阶乘计算

本文来源于微信公众号程序员小灰,有删改。

你可能感兴趣的:(算法)