大数加减乘以及高精度幂

我们都知道int, long, long long 等数据类型,但是如果一个数字过长的话,这些数据所定义的变量就放不下了,这时就要用到大数,所谓大数,就是比较大的数,超出了我们平时long long所定义的范围,这时可以用数组将它存放起来,用模拟手算的方式来让计算机计算,下面试关于大数的加减乘及高精度幂的代码实现

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #define NUM 10001//定义数组长度
  5 void showmeau();
  6 void change(char *ch1, char *ch2);
  7 void add(char *ch1, char *ch2);
  8 void sub(char *ch1, char *ch2);
  9 void Input();
 10 void add_big_number();
 11 void sub_big_number();
 12 void multi(char *ch1, char *ch2);
 13 void multi_big_number();
 14 void exchange(char *ch, int *count);
 15 void multi_power(char *ch, int n, int count);
 16 void high_precision_power();
 17 
 18 char s1[NUM], s2[NUM]; int n, flag = 0;
 19 int main()
 20 {
 21     showmeau();
 22     return 0;
 23 }
 24 void showmeau()
 25 {
 26     do{
 27         system("cls");//调用系统命令清屏
 28         printf("1. big number add  2. big number sub   \n3.big number multi  4. High precision power  \n\t\t0. exit\n");
 29         scanf("%d", &n);
 30         switch(n)
 31         {
 32         case 1:
 33             add_big_number();
 34             break;
 35         case 2:
 36             sub_big_number();
 37             break;
 38         case 3:
 39             multi_big_number();
 40             break;
 41         case 4:
 42             high_precision_power();
 43             break;
 44         case 0:
 45             break;
 46         default:
 47             printf("your input error!\n");
 48             break;
 49         }
 50         system("pause");
 51     }while(n != 0);
 52 
 53 }
 54 
 55 void Input()
 56 {
 57     printf("Input the first big number:\n");
 58     scanf("%s", s1);
 59     printf("Input the second big number:\n");
 60     scanf("%s", s2);
 61 }
 62 void change(char *ch1, char *ch2)//去掉负号函数
 63 {
 64     int len1 = strlen(ch1), len2 = strlen(ch2);
 65     int i;
 66     char str1[NUM], str2[NUM];
 67     switch(flag)
 68     {
 69     case 1:
 70         for(i = 0; i < len1 - 1; i ++)//如果都是负数的时候执行到ch1[1];
 71             str1[i] = ch1[len1 - i - 1];
 72         str1[i] = '\0';
 73         for(i = 0; i < len2 - 1; i ++)
 74             str2[i] = ch2[len2 - i - 1];
 75         str2[i] = '\0';
 76         break;
 77     case 2:
 78         for(i = 0; i < len1 - 1; i ++)//如果一正一负的话
 79             str1[i] = ch1[len1 - i - 1];
 80         str1[i] = '\0';
 81         for(i = 0; i < len2; i ++)
 82             str2[i] = ch2[len2 - i - 1];
 83         str2[i] = '\0';
 84         break;
 85     case 3:
 86         for(i = 0; i < len1; i ++)//如果一正一负的话
 87             str1[i] = ch1[len1 - i - 1];
 88         str1[i] = '\0';
 89         for(i = 0; i < len2 - 1; i ++)
 90             str2[i] = ch2[len2 - i - 1];
 91         str2[i] = '\0';
 92         break;
 93     case 4://如果都是正的
 94         for(i = 0; i < len1; i ++)
 95             str1[i] = ch1[len1 - i - 1];
 96         str1[i] = '\0';
 97         for(i = 0; i < len2; i ++){
 98             str2[i] = ch2[len2 - i - 1];
 99         }
100         str2[i] = '\0';
101         break;
102     default:
103         break;
104     }
105     memset(ch1, 0, sizeof(ch1));//将ch1清空
106     memset(ch2, 0, sizeof(ch2));//将ch2清空
107     strcpy(ch1, str1);
108     strcpy(ch2, str2);
109 }
110 void add(char *ch1, char *ch2)//执行加法过程
111 {
112     int len1 = strlen(ch1), len2 = strlen(ch2);
113     int t = 0, j;//t为进位;
114     int num[NUM] = {0}, i;
115     int max = len1 > len2 ? len1 : len2;//找出最大的长度来进行确定循环次数
116     for(i = 0; i < max; i ++)
117     {
118         if(len1 <= i)
119         {
120             if(ch2[i] + t - '0' > 9)//这是一位一位的进,
121             {
122                 num[i] = ch2[i] - '0' + t - 10;//只保存最后一位
123                 t = 1;
124             }
125             else
126             {
127                 num[i] = ch2[i] - '0' + t;
128                 t = 0;
129             }
130             continue;
131         }
132         else if(len2 <= i)
133         {
134             if(ch1[i] + t - '0' > 9)
135             {
136                 num[i] = ch1[i] - '0' + t - 10;
137                 t = 1;
138             }
139             else
140             {
141                 num[i] = ch1[i] - '0' + t;
142                 t = 0;
143             }
144             continue;
145         }
146         if(ch1[i] - '0' + ch2[i] - '0' + t > 9)
147         {
148             num[i] = ch1[i] + ch2[i] + t - '0' - '0' - 10;
149             t = 1;
150         }
151         else
152         {
153             num[i] = ch1[i] + ch2[i] + t - '0' - '0';
154             t = 0;
155         }
156     }
157     if(t == 1)
158         num[i] = 1;
159     if(num[i] == 1)
160         j = i;
161     else
162         j = i - 1;
163     for(; j >= 0; j --)
164         printf("%d", num[j]);
165     printf("\n");
166 }
167 void sub(char *ch1, char *ch2)//减法过程函数
168 {
169     char ch[NUM]; int num[NUM] = {0};
170     memset(ch, 0, sizeof(ch));
171     int flag = 0, i, j; char str1[NUM], str2[NUM];
172     int len1 = strlen(ch1), len2 = strlen(ch2);
173     if(len1 < len2)//判断两个数的大小,大的在前
174     {
175         strcpy(ch, ch1);
176         strcpy(ch1, ch2);
177         strcpy(ch2, ch);
178         flag = 1;//如果交换了,则说明前面的小,所以最后一定是负数
179     }
180     else if(len1 == len2)//当他们等长时,在比较究竟谁大一点
181     {
182         for(i = 0; i < len1; i ++)
183             str1[i] = ch1[len1 - i - 1];
184         str1[i] = '\0';
185         for(i = 0; i < len2; i ++)
186             str2[i] = ch2[len2 - i - 1];
187         str2[i] = '\0';
188         if(strcmp(str1, str2) < 0)
189         {
190             strcpy(ch, ch1);
191             strcpy(ch1, ch2);
192             strcpy(ch2, ch);
193             flag = 1;
194         }
195     }
196     len1 = strlen(ch1); len2 = strlen(ch2);
197     int t = 0;//定义借位
198     for(i = 0; i < len1; i ++)
199     {
200         if(len2 <= i)
201         {
202             if(ch1[i] - '0' + t < 0)
203             {
204                 num[i] = 10 + ch1[i] - '0' + t;
205                 t = -1;
206             }
207             else
208             {
209                 num[i] = ch1[i] - '0' + t;
210                 t = 0;
211             }
212             continue;
213         }
214         if(ch1[i] + t < ch2[i])
215         {
216             num[i] = 10 + ch1[i] - ch2[i] + t;
217             t = -1;
218         }
219         else
220         {
221             num[i] = ch1[i] - ch2[i] + t;
222             t = 0;
223         }
224     }
225     if(flag)
226         printf("-");//如果交换了,说明第一个数小于第二个数,要打印负号
227     for(i = len1; i >= 0; i --)//这里判断第一个数不为零的下标
228         if(num[i] != 0)
229             break;
230     if(i == -1)
231         printf("0");
232     for(j = i; j >= 0; j --)//从这个不为零的下标开始打印
233         printf("%d", num[j]);
234     printf("\n");
235 }
236 void multi(char *ch1, char *ch2)//乘法函数
237 {
238     int len1 = strlen(ch1), len2 = strlen(ch2);
239     int num[NUM] = {0}, i, j;
240     for(i = 0; i < len1; i ++)
241     {
242         for(j = 0; j < len2; j ++)
243         {
244             num[i + j] += (ch1[i] - '0') * (ch2[j] - '0');//先将各个数的乘积保存到int型变量数组中,即num中,然后最后在进行进位
245         }
246     }
247     int t = 0, tmp;//临时变量来保存num + t 的值,因为一计算num[i],num就变啦
248     for(i = 0; i < len1 + len2 - 1; i ++)
249     {
250         if(num[i] + t > 9)
251         {
252             tmp = num[i] + t;
253             num[i] = (t + num[i]) % 10;
254             t = tmp / 10;//t用来保存进位
255 
256         }
257         else
258         {
259             num[i] += t;
260             t = 0;
261         }
262     }
263     while(t > 9)//如果最后一位不为零,说明有进位
264     {
265         num[i ++] = t % 10;
266         t = t / 10;
267     }
268     if(t != 0)
269         num[i] = t;
270     if(num[i] != 0)
271         j = i;
272     else
273         j = i - 1;
274     for(; j >= 0; j --)
275         printf("%d", num[j]);
276     printf("\n");
277 
278 }
279 void exchange(char *ch, int *count)//逆置函数
280 {
281     int len = strlen(ch), i, j;
282     char str[NUM];
283     j = 0;
284     for(i = len -1; i >= 0; i --)//判断如果后面有多余的零, 清除掉
285     {
286         if(ch[i] == '0')
287         {
288             len --;
289         }
290         else
291             break;
292     }
293     for(; i >= 0; i --)
294     {
295         if(ch[i] == '.')//当读到点的时候,这时记录小数点位数,将它存入count中
296         {
297             *count = len - i - 1;
298             continue;
299         }
300         str[j++] = ch[i];
301     }
302     str[j] = '\0';//字符串结束符
303     strcpy(ch, str);
304 }
305 void multi_power(char *ch, int n, int count)
306 {
307     int i, j, k, y; char ch1[NUM], ch2[NUM];//ch1用来存放计算时的第一个数,ch2用来存放临时结果
308     memset(ch1, 0, sizeof(ch1));
309     memset(ch2, 0, sizeof(ch2));
310     strcpy(ch1, ch); int t = 0;
311     for(i = 1; i < n; i ++)//一共循环n-1次
312     {
313 
314         for(j = 0; j < strlen(ch); j ++)//执行大数加法运算,这时的数已经没有小数点了
315         {
316             t = 0; int tmp = 0;
317             for(k = 0; k < strlen(ch1); k ++)
318             {
319                 ch2[j + k] += (ch[j] - '0') * (ch1[k] - '0');//将它存入ch2中
320                 if(ch2[j + k] + t > 9)//判断是否满足进位,此时存入的是ascii码
321                 {
322                     tmp = ch2[j + k] + t;
323                     ch2[j + k] = (ch2[j + k] + t) % 10;
324                     t = tmp / 10;
325                 }
326                 else
327                 {
328                     ch2[j + k] += t;
329                     t = 0;
330                 }
331             }
332             y = j + k;
333             while(t > 9)//判断到最后还有没有进位
334             {
335                 ch2[y ++] = t % 10;
336                 t /= 10;
337             }
338             if(t != 0)//最后一个进位
339                 ch2[y++] = t;
340         }
341         ch2[y] = '\0';//结束符
342         memset(ch1, 0, sizeof(ch1));//将ch1清空
343         int x;
344         for(x = 0; x < y; x ++)
345         {
346             ch2[x] += '0';//将ascii转化成字符123...
347         }
348         strcpy(ch1, ch2);
349         memset(ch2, 0, sizeof(ch2));
350     }
351     int flag = 0;
352     for(i = strlen(ch1) - 1; i >= 0; i --)//打印出来结果
353     {
354         if(i == n * count - 1)
355         {
356             printf(".");
357             flag = 1;
358         }
359         if(flag)
360         {
361             if(ch1[i] == 0)
362                 continue;
363         }
364         printf("%c", ch1[i]);
365     }
366     printf("\n");
367 }
368 void add_big_number()
369 {
370     Input();
371     if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数
372         flag = 1;
373     else if(s1[0] == '-' && s2[0] != '-')//如果一正一负
374         flag = 2;
375     else if(s1[0] != '-' && s2[0] == '-')//如果一正一负
376         flag = 3;
377     else//如果全为正
378         flag = 4;
379     change(s1, s2);//调用交换函数,将它们调整好顺序,去掉负号,并且将字符串逆序
380     switch(flag)
381     {
382     case 1:
383         printf("-");
384         add(s1, s2);//调用加法函数输出结果
385         break;
386     case 2:
387         sub(s2, s1);//调用减法函数来计算结果并将其输出
388         break;
389     case 3:
390         sub(s1, s2);//调用减法函数来计算结果并将其输出
391         break;
392     case 4:
393         add(s1, s2);//调用加法函数输出结果
394         break;
395     }
396 }
397 
398 void sub_big_number()
399 {
400     Input();
401     if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数
402         flag = 1;
403     else if(s1[0] == '-' && s2[0] != '-')//如果一正一负
404         flag = 2;
405     else if(s1[0] != '-' && s2[0] == '-')//如果一正一负
406         flag = 3;
407     else//如果全为正
408         flag = 4;
409     change(s1, s2);//调用交换函数,将它们调整好顺序,去掉负号,并且将字符串逆序
410     switch(flag)
411     {
412     case 1:
413         sub(s2, s1);//调用减法函数输出结果
414         break;
415     case 2:
416         printf("-");
417         add(s1, s2);//调用加法函数来计算结果并将其输出
418         break;
419     case 3:
420         add(s1, s2);//调用加法函数来计算结果并将其输出
421         break;
422     case 4:
423         sub(s1, s2);//调用减法函数输出结果
424         break;
425     }
426 }
427 void multi_big_number()
428 {
429     Input();
430     if(s1[0] == '-' && s2[0] == '-')//如果两个数都为负数
431         flag = 1;
432     else if(s1[0] == '-' && s2[0] != '-')//如果一正一负
433         flag = 2;
434     else if(s1[0] != '-' && s2[0] == '-')//如果一正一负
435         flag = 3;
436     else//如果全为正
437         flag = 4;
438     change(s1, s2);
439     if(flag == 2 || flag == 3)
440         printf("-");
441     multi(s1, s2);
442 }
443 void high_precision_power()
444 {
445     int n, count = 0;
446     printf("Input the high precision power number:\n");
447     scanf("%s", s1);
448     printf("Input the power number:\n");
449     scanf("%d", &n);
450     exchange(s1, &count);
451     multi_power(s1, n, count);
452 }

 

posted @ 2014-08-21 16:56  Howe_Young  阅读(264)  评论(1编辑  收藏  举报