本文轉載至:http://blog.csdn.net/hitwhylz/article/details/9700935,并加以完善。
完善内容:增加了餘數的輸出。
大數除法,應該算是四則運算裡面最難的一種了。不同于一般的模拟,除法操作步數模仿手工除法,而是利用減法操作實作的。
其基本思想是反複做除法,看從被除數裡面最多能減去多少個除數,商就是多少。
逐個減顯然太慢,要判斷一次最多能減少多少個整的10的n次方。
以7546除23為例。
先減去23的100倍,就是2300,可以減3次,餘下646。 此時商就是300;
然後646減去23的10倍,就是230,可以減2次,餘下186。此時商就是320;
然後186減去23,可以減8次,此時商就是328.
根據這個思想,不難寫出下面的代碼。
還是那句話,可能算法效率不是很高。但是正常解題思路一般就是這樣了。
如果以後有能力,有時間了。 我會試着去優化。
ps:大數系列學習資源來自 <c程式設計競賽實訓教程>一書和一些大牛的部落格。
注意:程式不保留小數(隻有商,沒有餘數),看了很多程式都是沒有小數。
1 /*
2 本程式說明:
3
4 大數除法 http://blog.csdn.net/hitwhylz/article/details/9700935
5
6 */
7
8 #include<stdio.h>
9 #include<string.h>
10 #include<stdlib.h>
11 #define MaxLen 200
12 //函數SubStract功能:
13 //用長度為len1的大整數p1減去長度為len2的大整數p2
14 // 結果存在p1中,傳回值代表結果的長度
15 //不夠減 傳回-1 正好夠 傳回0
16 int SubStract( int *p1, int *p2, int len1, int len2 )
17 {
18 int i;
19 if( len1 < len2 )
20 return -1;
21 if( len1 == len2 )
22 { //判斷p1 > p2
23 for( i=len1-1; i>=0; i-- )
24 {
25 if( p1[i] > p2[i] ) //若大,則滿足條件,可做減法
26 break;
27 else if( p1[i] < p2[i] ) //否則傳回-1
28 return -1;
29 }
30 }
31 for( i=0; i<=len1-1; i++ ) //從低位開始做減法
32 {
33 p1[i] -= p2[i];
34 if( p1[i] < 0 ) //若p1<0,則需要借位
35 {
36 p1[i] += 10; //借1當10
37 p1[i+1]--; //高位減1
38 }
39 }
40 for( i=len1-1; i>=0; i-- ) //查找結果的最高位
41 if( p1[i] ) //最高位第一個不為0
42 return (i+1); //得到位數并傳回
43 return 0; //兩數相等的時候傳回0
44 }
45 int main()
46 {
47 int n, k, i, j; //n:測試資料組數
48 int len1, len2; //大數位數
49 int nTimes; //兩大數相差位數
50 int nTemp; //Subtract函數傳回值
51 int num_a[MaxLen]; //被除數
52 int num_b[MaxLen]; //除數
53 int num_c[MaxLen]; //商
54 char str1[MaxLen + 1]; //讀入的第一個大數
55 char str2[MaxLen + 1]; //讀入的第二個大數
56
57 scanf("%d",&n);
58 while ( n-->0 )
59 {
60 scanf("%s", str1); //以字元串形式讀入大數
61 scanf("%s", str2);
62
63 for ( i=0; i<MaxLen; i++ ) //初始化清零操作
64 {
65 num_a[i] = 0;
66 num_b[i] = 0;
67 num_c[i] = 0;
68 }
69
70 len1 = strlen(str1); //獲得大數的位數
71 len2 = strlen(str2);
72
73 for( j=0, i=len1-1; i>=0; j++, i-- )
74 num_a[j] = str1[i] - '0'; //将字元串轉換成對應的整數,颠倒存儲
75 for( j=0, i=len2-1; i>=0; j++, i-- )
76 num_b[j] = str2[i] - '0';
77
78 if( len1 < len2 ) //如果被除數小于除數,結果為0
79 {
80 printf("0\n");
81 continue; //利用continue直接跳出本次循環。 進入下一組測試
82 }
83 nTimes = len1 - len2; //相差位數
84 for ( i=len1-1; i>=0; i-- ) //将除數擴大,使得除數和被除數位數相等
85 {
86 if ( i>=nTimes )
87 num_b[i] = num_b[i-nTimes];
88 else //低位置0
89 num_b[i] = 0;
90 }
91 len2 = len1;
92 for( j=0; j<=nTimes; j++ ) //重複調用,同時記錄減成功的次數,即為商
93 {
94 while((nTemp = SubStract(num_a,num_b + j,len1,len2 - j)) >= 0)
95 {
96 len1 = nTemp; //結果長度
97 num_c[nTimes-j]++;//每成功減一次,将商的相應位加1
98 }
99 }
100
101 //輸出商
102 for( i=MaxLen-1; num_c[i]==0 && i>=0; i-- );//跳過高位0
103 if( i>=0 )
104 for( ; i>=0; i-- )
105 printf("%d", num_c[i]);
106 else
107 printf("0");
108 printf("\n");
109
110
111 //此時的num_a存的就是餘數(其實就是取模)
112 for( i=MaxLen-1; num_a[i]==0 && i>=0; i-- );//跳過高位0
113 if( i>=0 )
114 for( ; i>=0; i-- )
115 printf("%d", num_a[i]);
116 else
117 printf("0");
118 printf("\n");
119
120 }
121 return 0;
122 }
同類文章:
【模闆小程式】 十進制大數相乘(正數、負數、0均可),包含合法性檢查:http://www.cnblogs.com/xiaoxi666/p/7272255.html
【模闆小程式】十進制大數相加(正整數版本+整數版本【正負0】),包含合法性檢查:http://www.cnblogs.com/xiaoxi666/p/7258312.html
『注:本文來自部落格園“小溪的部落格”,若非聲明均為原創内容,請勿用于商業用途,轉載請注明出處http://www.cnblogs.com/xiaoxi666/』