P1303 A*B Problem

题目描述

给出两个非负整数,求它们的乘积。

输入格式

输入共两行,每行一个非负整数。

输出格式

输出一个非负整数表示乘积。

样例 #1

样例输入 #1

1 
2

样例输出 #1

2

提示

每个非负整数不超过 1 0 2000 10^{2000} 102000

1.题目分析

输入两个数,计算乘积。
因为是大数运算,所以直接算肯定超数据类型范围。

这里同样和两数之和的高精度一样,使用字符数组输入后,
根据两数乘积运算法则进行相关计算。

由于字符串数组输入两个数字存在长度不一致,导致运算错位的问题,
这里提供两种解决思路:

第一,前置补零运算,让长度较短的数前面补零和长度较长的数长度一致。
只是后续输出结果,处理起来比较麻烦,涉及到进位问题,需要将结果数组元素后移的问题。

第二,将输入的两个数逆序存储到整型数组中,这样就保证了运算位对位正确,然后将每一轮计算结果累加到结果数组的相应位置,再让大于9的元素进位,这样就得到了同样逆序的结果,再将结果逆序输出即可。

本题代码采用第二种方式计算。

举个例子:当计算1234 * 789时,必然涉及到进位问题,
(1)先让两个数逆序:

4 3 2 1
9 8 7 0

(2)然后将每一轮结果累加得到逆序但未进位的输出:

36 59 70 46 22 7

(3)依次进位:

6 2 6 3 7 9 

(4)逆序输出:

973626

2.题目思路

输出两个字符串,获取输入的字符长度,

反转存入整型数组,目的是,当两个乘数的长度不一致时,反转之后每一次计算的位置不会受到影响,
反转过程中,减去字符’0’,赋值给对应整型数组。

然后进行上述分析中的两数相乘运算,将任一一位乘数的一位与另一个乘数的每一位相乘,
结果累加在另一个数组相应的位置,计算出的是未进位的逆序结果。

接下来就是进位操作:
这里循环的次数为两个乘数的长度和,因为两数之积的位数不会大于原本两数的长度之和。
当元素大于9时,先进位,因为是逆序,前一位数字就是现在数组的后一位,后计算余数 即当前位。

结束后,逆序(当第一次遇到非零数字后,开始输出)打印输出即可。
值得一提的是,需要特判零:
当上述遍历全为零时,则结果为零,打印零即可。

3.代码实现

#include 
#include 

using namespace std;

int main() {
    //用于输入
    char a[2001], b[2001];
    //整型数组用于计算
    int a1[2001], b1[2001], m1[4001];
    //输入两个大数
    cin >> a >> b;
    //获取输入的字符长度
    int len1 = strlen(a);
    int len2 = strlen(b);
    //反转存入整型数组
    //目的是,当两个乘数的长度不一致时,反转之后每一次计算的位置不会受到影响
    for (int i = 0; i < len1; ++i) {
        //减去字符'0',赋值给对应整型数组
        a1[i] = a[len1 - 1 - i] - '0';
    }
    for (int i = 0; i < len2; ++i) {
        b1[i] = b[len2 - 1 - i] - '0';
    }
    //两数相乘:将任一一位乘数的一位与另一个乘数的每一位相乘,
    // 结果累加在另一个数组相应的位置
    for (int i = 0; i < len1; ++i) {
        for (int j = 0; j < len2; ++j) {
            //数学规律:计算出的是未进位的逆序结果:
            // 例如12*12 在这里的结果就是4 4 1,实际结果逆序为144即可。
            m1[i + j] += a1[i] * b1[j];
        }
    }
    //进位
    //两数之积的位数不会大于原本两数的长度之和
    for (int i = 0; i < len1 + len2; ++i) {
        //满十进几
        if (m1[i] > 9) {
            //先进位,因为是逆序,前一位数字就是现在数组的后一位
            m1[i + 1] += m1[i] / 10;
            //计算余数 即当前位
            m1[i] %= 10;
        }
    }
    //标记符
    int cnt = 1;
    //逆序输出:当第一次遇到非零数字后,开始输出
    for (int i = len2 + len1; i >= 0; i--) {
        //判断非零
        if (m1[i] != 0 && cnt == 1) {
            cnt--;
        }
        //输出
        if (cnt == 0) {
            cout << m1[i];
        }
    }
    //特判零:当上述遍历全为零时,则结果为零,打印零即可。
    if (cnt == 1) {
        cout << 0;
    }
    return 0;
}

你可能感兴趣的:(刷题go,go,go,算法,数据结构,c++)