华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)

题目描述: 输出两个不超过100位的大整数的乘积。
输入: 输入两个大整数,如1234567 123
输出: 输出乘积,如:151851741
样例输入: 1234567 123
样例输出: 151851741

 

注意:在oj上不能直接套用我的代码,需要将无关的输出去除才行

方法一

思路:

解这道题目最简单的方法就是模拟我们笔算乘法的过程,如:1234×123

华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)

只要把这个过程实现,无论多大的数我们都能解决了,是不是很简单。

程序实现:

首先,我们用两个字符串来保存我们的大整数,num1[100], num2[100]

scanf("%s%s", num1, num2);

然后,求num2的每一位与num1的乘积,保存到tempRes中。

过程为:res保存每位相乘的结果,carry用来保存进位,每位相乘之后还要加上进位才是真的结果。将res的个位保存到tempRes中,其他位则为下一位相乘的进位。

    for(j = num2Len - 1; j >= 0; j--)
    {
        /*计算num1与num2各位相乘的结果,保存到tempRes中
         *每一位相乘后与之前的进位相加得出res,将res的个
         *位(res%10)保存到tempRes里,然后将res的其余位数
         *(res/10)则为进位carry*/
        for(i = num1Len-1; i >= 0; i--)
        {
            res = Int(num1[i]) * Int(num2[j]) + carry;
            tempRes[tempResLen--] = Char(res % 10);
            carry = res / 10;
        }
        //tempRes第一位为进位,刚刚的循环是没有算的,最后把进位算上
        tempRes[tempResLen] = Char(carry);
        tempResLen = num1Len;
        carry = 0;
    }

再然后,将tempRes与result求和,每求一次,向左偏移一位。res为每位之和再加上进位,这里很重要,然后保存到result里只是res的个位,res为下一位计算的进位。

//由result的末尾开始计算和,算完一次,向左偏移一位
for(k = resultLen-offset; k > (resultLen-offset-num1Len); k--)
{
    res = Int(result[k]) + Int(tempRes[tempResLen--]) + carry;
    result[k] = Char(res%10);
    carry = res/10;
}
result[k] += Int(tempRes[tempResLen] + carry);
offset++;

以上两步就是我程序最核心的部分。以下是程序的全部代码

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<malloc.h>
  4 
  5 #define and &&
  6 #define or ||
  7 #define not !
  8 #define Int(X) (X - '0')
  9 #define Char(X) (X + '0')
 10 
 11 char *multiBigInteger(const char *, const char *);
 12 int checkNum(const char *);
 13 
 14 int main(void)
 15 {
 16     char num1[100] = {'\0'}, num2[100] = {'\0'};
 17     while(scanf("%s%s", num1, num2) != EOF)
 18     {
 19         char *result = "0";
 20         if(strlen(num1) > 100 or strlen(num2) > 100)
 21         {
 22             printf("ERROR\n");
 23             return 1;
 24         }
 25         if(checkNum(num1) or checkNum(num2))
 26         {
 27             printf("ERROR: input must be an Integer\n");
 28             return 1;
 29         }
 30         printf("num1:\t%s\nnum2:\t%s\n", num1, num2);
 31         result = multiBigInteger(num1, num2);
 32         if(result[0] == '0')
 33         {
 34             int i;
 35             printf("result:\t");
 36             for(i = 1; (size_t)i < strlen(result); i++)
 37             {
 38                 printf("%c", result[i]);
 39             }
 40             printf("\n");
 41         }
 42         else
 43         {
 44             printf("result:\t%s\n", result);
 45         }
 46         printf("\n");
 47     }
 48     return 0;
 49 } 
 50 
 51 int checkNum(const char *num)
 52 {
 53     int i;
 54     for(i = 0; (size_t)i < strlen(num); i++)
 55     {
 56         if(num[i] < '0' or num[i] > '9')
 57         {
 58             return 1;
 59         }
 60     }
 61     return 0;
 62 }
 63 
 64 char *multiBigInteger(const char *num1, const char *num2)
 65 {
 66     char *tempRes = NULL;              //用来保存每次相乘的结果
 67     char *result = NULL;               //用来保存最终结果
 68     int tempResLen;                    //每次相乘结果的最大长度
 69     int num1Len = strlen(num1);        //num1的长度
 70     int num2Len = strlen(num2);        //num2的长度
 71     int resultLen;                     //结果的最大长度
 72     int i, j, k;                       //循环计数器
 73     int res;                           //每次一位相乘/相加的结果
 74     int carry = 0;                     //进位
 75     int offset = 0;                    //加法的偏移位
 76     resultLen = num1Len + num2Len - 1; //结果长度最大为num1长度和num2长度之和,由于下标从0开始,所以要减一
 77     tempResLen = num1Len;              //每次num1乘以num2每一位的结果最大长度是num1Len+1,由于下标从0开始,所以减一后约去1,只剩num1Len
 78     //初始化result为0
 79     result = (char *)malloc((resultLen+2)*sizeof(char));
 80     memset(result, '0', (resultLen+1)*sizeof(char));
 81     result[resultLen+1] = 0;
 82 
 83     tempRes = (char *)malloc((tempResLen+2)*sizeof(char));
 84     for(j = num2Len - 1; j >= 0; j--)
 85     {
 86         //初始化tempRes每位为0
 87         memset(tempRes, '0', (tempResLen+1)*sizeof(char));
 88         /*计算num1与num2各位相乘的结果,保存到tempRes中
 89          *每一位相乘后与之前的进位相加得出res,将res的个
 90          *位(res%10)保存到tempRes里,然后将res的其余位数
 91          *(res/10)则为进位carry*/
 92         for(i = num1Len-1; i >= 0; i--)
 93         {
 94             res = Int(num1[i]) * Int(num2[j]) + carry;
 95             tempRes[tempResLen--] = Char(res % 10);
 96             carry = res / 10;
 97         }
 98         //tempRes第一位为进位,刚刚的循环是没有算的,最后把进位算上
 99         tempRes[tempResLen] = Char(carry);
100         tempResLen = num1Len;
101         carry = 0;
102         //由result的末尾开始计算和,算完一次,向左偏移一位
103         for(k = resultLen-offset; k > (resultLen-offset-num1Len); k--)
104         {
105             res = Int(result[k]) + Int(tempRes[tempResLen--]) + carry;
106             result[k] = Char(res%10);
107             carry = res/10;
108         }
109         result[k] += Int(tempRes[tempResLen] + carry);
110         carry = 0;
111         tempResLen = num1Len;
112         offset++;
113 
114     }
115     printf("num1Len:%d\nnum2Len:%d\n", num1Len, num2Len);
116     return result;
117 }
大整数相乘完整代码

相关文章: