| 题目描述: | 输出两个不超过100位的大整数的乘积。 |
| 输入: | 输入两个大整数,如1234567 123 |
| 输出: | 输出乘积,如:151851741 |
| 样例输入: | 1234567 123 |
| 样例输出: | 151851741 |
注意:在oj上不能直接套用我的代码,需要将无关的输出去除才行
方法一
思路:
解这道题目最简单的方法就是模拟我们笔算乘法的过程,如:1234×123
只要把这个过程实现,无论多大的数我们都能解决了,是不是很简单。
程序实现:
首先,我们用两个字符串来保存我们的大整数,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 }