數據結構設計——大數計算器


  1 /*
  2 大數計算器
  3
  4 實驗目的:數據結構主要是研究計算機存儲,組織數據,非數值計算程序設計問題中所 出現的計算機操作對象以及它們之間的關系和操作的學科。數據結構是介於數學、計算機軟件和計算機硬件之間的一門計算機專業的核心課程,它是計算機程序設計、數據庫、操作系統、編譯原理及人工智能等的重要基礎,廣泛的應用於信息學、系統工程等各種領域。學習數據結構是為了將實際問題中涉及的對象在計算機中表示出來並對它們進行處理。通過課程設計可以提高學生的思維能力,促進學生的綜合應用能力和專業素質的提高。
  5
  6
  7
  8 實驗要求:要求包含加、減、乘、除、取余的兩個超出普通計算器范圍的大數運算。
  9
10
11 程序代碼:
12 *******************************************************************************
13 */
  1 //Large_Number.h
  2 #define MAXSIZE 200
  3 #define TMAXSIZE 400
  4 
  5 typedef class SeqList {
  6 public:
  7     int data[TMAXSIZE];
  8     int length;
  9 public:
 10     SeqList(){};
 11     SeqList * operator +( SeqList *P2) ;
 12     SeqList * operator -( SeqList *P2) ;
 13     SeqList * operator *( SeqList *P2) ;
 14     SeqList * operator /( SeqList *P2) ;
 15     SeqList * operator %( SeqList *P2) ;
 16     int operator <( SeqList *P2) ;
 17 } *PSeqList;
 18 
 19 //函數申明區
 20 PSeqList Init_SeqList(void);//創建一個順序表
 21 PSeqList Input_SeqList(PSeqList L, char a[]);//將數據輸入到順序表中
 22 int Length_SeqList(PSeqList L);//獲得表長度
 23 void Output_SeqList(PSeqList PL);//輸出順序表
 24 void Distory_SeqList(PSeqList PL);
 25 PSeqList e_zero(PSeqList P3);//擦除多余的0
 26 PSeqList NInput_SeqList(PSeqList L, int n);//普通數轉化為大數
 27 
 28 //兩個多項式或者大數相乘
 29 PSeqList SeqList::operator *( SeqList *P2) 
 30 {
 31     int addlength = 0, i, j;
 32     PSeqList P3;
 33     P3 = Init_SeqList();
 34     i = length;
 35     j = P2->length;
 36     addlength = i + j;
 37     for (i = 0; i < addlength; i++)
 38         P3->data[i] = 0;
 39     P3->length = i;
 40     for (i = length - 1; i >= 0; i--)
 41         for (j = P2->length - 1; j >= 0; j--)
 42         {
 43             P3->data[i + j + 1] += (data[i] * P2->data[j]);
 44             if (P3->data[i + j + 1] >= 10)//如果P3->data的第i+j+1位大於或等於10,要讓它進位
 45             {
 46                 P3->data[i + j] += P3->data[i + j + 1] / 10;
 47                 P3->data[i + j + 1] = P3->data[i + j + 1] % 10;
 48             }
 49         }
 50     P3 = e_zero(P3);
 51     return P3;
 52 }
 53 
 54 PSeqList SeqList::operator +( SeqList *P2) 
 55 {
 56     PSeqList P3;
 57     int i, j, ijmax, count = 0;
 58     int P1_0 = data[0];
 59     int P2_0 = P2->data[0];//保留下面操作中將要修改的值
 60     P3 = Init_SeqList();
 61     i = length;
 62     j = P2->length;
 63     ijmax = i > j ? i : j;
 64     for (i = 0; i < ijmax + 1; i++)//比最大長度大一個,這樣不會有溢出位
 65         P3->data[i] = 0;//給所有位數置零
 66     P3->length = ijmax + 1;
 67     for (i = length - 1, j = P2->length - 1; count < ijmax; count++)
 68         //當P1、P2中都有數據時,兩者同時向前移動一個單位,計數加1
 69     {
 70         P3->data[ijmax - count] += (data[i] + P2->data[j]);
 71         if (P3->data[ijmax - count] >= 10)
 72         {
 73             P3->data[ijmax - count - 1] = P3->data[ijmax - count] / 10;
 74             P3->data[ijmax - count] = P3->data[ijmax - count] % 10;
 75         }
 76         if (i >= 0) i--;//P1還有數,減一
 77         if (i < 0){//P1沒有數,數data[0] = 0;
 78             i = 0; data[i] = 0;
 79         }
 80         if (j >= 0) j--;
 81         if (j < 0){//P2沒有數,數data[0] = 0;
 82             j = 0; P2->data[j] = 0;
 83         }
 84     }
 85     data[0] = P1_0;
 86     P2->data[0] = P2_0;//還原修改的值
 87     P3 = e_zero(P3);
 88     return P3;
 89 }
 90 
 91 //多項式相減,分前后值P1-P2
 92 PSeqList SeqList::operator -(SeqList *P2)
 93 {
 94     PSeqList P3;
 95     int i, j, ijmax, count = 0, ismz = 0, cf;//ismz來判斷結果的正負,如果為負數,ismz為1,k表示進位標志
 96     int P1_0 = data[0];
 97     int P2_0 = P2->data[0];//保留下面操作中將要修改的值
 98     P3 = Init_SeqList();
 99     i = length;
100     j = P2->length;
101     ijmax = i > j ? i : j;
102     for (i = 0; i < ijmax; i++)//和最大長度相同,這樣不會有溢出位
103         P3->data[i] = 0;//給所有位數置零
104     P3->length = ijmax;
105     for (i = length - 1, j = P2->length - 1; count < ijmax; count++)//當P2中都有數據時,兩者同時向前移動一個單位,計數加1
106     {
107         P3->data[ijmax - count - 1] += (data[i] - P2->data[j]);
108         if (P3->data[ijmax - count - 1] < 0)
109         {    
110             if (ijmax - count - 1 != 0)//因為當ijmax - count - 1 = 0時,P3->data[ijmax-count-2] 等價於P3->data[-1],不存在,編譯過程中會出現問題
111                 P3->data[ijmax - count - 2] -= 1;
112             else
113             {
114                 ismz = 1;
115             }
116             P3->data[ijmax - count - 1] = P3->data[ijmax - count - 1] + 10;
117         }
118         if (i >= 0) i--;//P1還有數,減一
119         if (i < 0){//P1沒有數,數data[0] = 0;
120             i = 0; data[i] = 0;
121         }
122         if (j >= 0) j--;
123         if (j < 0){//P2沒有數,數data[0] = 0;
124             j = 0; P2->data[j] = 0;
125         }
126     }
127     data[0] = P1_0;
128     P2->data[0] = P2_0;//還原修改的值
129     if (ismz == 1)
130     {
131         for (cf = 0, count = 0; count < ijmax; count++)//當P2中都有數據時,兩者同時向前移動一個單位,計數加1
132         {
133             P3->data[ijmax - count - 1] = 0 - P3->data[ijmax - count - 1] - cf;
134             cf = 0;
135             if (P3->data[ijmax - count - 1] < 0)
136             {
137                 cf = 1;
138                 P3->data[ijmax - count - 1] = P3->data[ijmax - count - 1] + 10;
139             }
140         }
141         P3 = e_zero(P3);
142         P3->data[0] *= -1;
143     }
144     P3 = e_zero(P3);
145     return P3;
146 }//end減法
147 
148 PSeqList SeqList::operator /(SeqList *P2)//取整操作
149 {
150     PSeqList P1 = this;
151     PSeqList P3;
152     PSeqList P4;
153     P3 = Init_SeqList();
154     P4 = Init_SeqList();
155     P3->length = length - P2->length + 1;
156     if (P3->length < 0)//如果前者小於后者,結果為0
157     {
158         P3->length = 1;
159         P3->data[0] = 0;
160         return P3;//返回,結束操作
161     }
162     for (int i = P3->length-1; i >= 0; i--)
163     {
164         int j = 0;
165         P4 = NInput_SeqList(P4,  i);
166         P4 = *P4 * P2;
167         while (1){
168             if (*P1 < P4)  break;
169             P1 = *P1 - P4;
170             j++;
171         }
172         P3->data[P3->length -1 - i] = j;
173     }
174     Distory_SeqList(P4);
175     P3 = e_zero(P3);
176     return P3;
177 }
178 PSeqList SeqList::operator %(SeqList *P2)
179 {
180     PSeqList P1 = this;
181     PSeqList P3;
182     P3 = Init_SeqList();
183     P3 = *P1 - (*(*P1 / P2)*P2);
184     P3 = e_zero(P3);
185     return P3;
186 }
187 
188 int SeqList::operator < (SeqList *P2)
189 {
190     SeqList *P3 = this;
191     if (length < P2->length)
192         return 1;
193     if (length > P2->length)
194         return 0;
195     if ((*P3 - P2)->data[0] < 0)
196         return 1;
197     else
198         return 0;
199 }
200 
201 
202 //創建一個順序表,入口參數無,返回一個指向順序表的指針,指針值為零表示分配空間失敗
203 PSeqList Init_SeqList(void)
204 {
205     PSeqList PL;
206     PL = (PSeqList)malloc(sizeof(SeqList));
207     if (PL)
208         PL->length = 0;
209     else
210     {
211         cout << "內存分配失敗..." << endl;
212         exit(-1);
213     }
214     return (PL);
215 }
216 
217 //數據輸入
218 PSeqList Input_SeqList(PSeqList L, char a[])
219 {
220     int i, a_length = 0;
221     a_length = strlen(a);
222     for (i = 0; i < a_length; i++)
223         L->data[i] = (int)a[i] - '0';//將char型整數轉換成int型整數
224     L->length = i;
225     return L;
226 }
227 PSeqList NInput_SeqList(PSeqList L, int n)
228 {
229     int i;
230     L->data[0] = 1;
231     for (i = 1; i <= n; i++)
232         L->data[i] = 0;
233     L->length = n+1;
234     return L;
235 }
236 
237 //讀取順序表的當前長度
238 int Length_SeqList(PSeqList L)
239 {
240     if (!L)
241     {
242         cout << "無PL指針,退出程序..." << endl;
243         exit(-1);
244     }
245     return (L->length);
246 }
247 
248 //順序表整體輸出
249 void Output_SeqList(PSeqList PL)
250 {
251     int i;
252     for (i = 0; i < PL->length; i++)
253         cout << PL->data[i];
254 }
255 
256 PSeqList e_zero(PSeqList P3)//擦除多余的0
257 {
258     int count = 0;
259     for (int i = 0; i < P3->length - 1; i++) //如果i和count 同時增加,則說明P3->data[i]為0,則為默認值,可以去掉,保留下來的就是有效的數據
260         if (P3->data[i] == 0 && i == count)
261             count++;        
262     if (count != 0)
263         for (int i = 0; i < P3->length - 1; i++)
264             P3->data[i] = P3->data[i + count];
265     P3->length -= count;//實參傳進來的位數總和去掉無效位數就是,結果順序表的長度
266     return P3;
267 }
268 
269 void Distory_SeqList(PSeqList PL)
270 {
271     free(PL->data);
272 }
273 
274 //end Large_Number.h
275 **************************************************************************************************************
276 //Large_Number_calculator.cpp
277 //可以實現兩個200位以內的數值運算,如果需要運算更大的數可以將宏定義中的長度增大
278 #include<iostream>
279 #include<cmath>
280 #include<cstring>
281 #include<windows.h>
282 using namespace std;
283 
284 #include"Large_Number.h"
285 
286 //主函數
287 int main(void)
288 {
289     //將一個長整形按位分開,依次存放在數組data中
290     PSeqList P1, P2, P3;
291     char a[MAXSIZE], b[MAXSIZE];
292     char order = 4;    
293     int keep_result = 0;
294     P1 = Init_SeqList();
295     P2 = Init_SeqList();
296     while (1)
297     {
298         int is_exit;
299     
300         int operate = 1;
301         if (keep_result != 1)
302         {
303             cout << "請輸入大數a 操作符 大數b (中間用空格或換行隔開):" << endl;
304             cin >> a;
305             P1 = Input_SeqList(P1, a);    
306         }
307         else
308         {
309             P1 = P3;
310             cout << "請輸入 操作符 大數b (中間用空格或換行隔開):" << endl;    
311         }
312         cin >> order >> b;
313         P2 = Input_SeqList(P2, b);
314         switch (order)
315         {
316         case '+':P3 = *P1 + P2; break;
317         case '-':P3 = *P1 - P2; break;
318         case '*':P3 = *P1 * P2; break;
319         case '/':P3 = *P1 / P2; break;
320         case '%':P3 = *P1 % P2;    break;
321         default:
322             cout << "錯誤的操作符,無法進行操作..." << endl;
323             operate = 0;//操作失敗標志
324         }
325         if (operate == 1)
326         {
327             int i;
328             int max_length = P1->length > P2->length ? P1->length : P2->length;
329             max_length = max_length > P3->length ? max_length : P3->length;
330             for (i = 0; i < max_length + 4; i++)
331                 cout << "-";
332             cout << endl;
333             if (P1->length >= P2->length)  {
334                 cout << "  ";
335                 Output_SeqList(P1);
336                 cout << "\n" << order << " ";
337                 for (i = 0; i < P1->length - P2->length; i++) cout << " ";
338                 Output_SeqList(P2);
339             }
340             else {
341                 for (i = 0; i < P2->length - P1->length + 2; i++)
342                     cout << " ";
343                 Output_SeqList(P1);
344                 cout << "\n" << order << " ";
345                 Output_SeqList(P2);
346             }
347             cout << endl;
348             for (i = 0; i < max_length + 6; i++)
349                 cout << "-";
350             cout << "\n= ";
351             Output_SeqList(P3);
352             cout << "\n結果的的長度:" << Length_SeqList(P3) << endl;
353         }
354         cout << "是否繼續運算?,任意字符、退出,1、繼續 : " ;
355         cin >> is_exit;
356         if (is_exit != 1)   break;
357         cout << "是否保留上次運算結果並在此基礎上進行運算(1、保存,其他、不保存) : ";
358         cin >> keep_result;
359     }    
360     Distory_SeqList(P1);
361     Distory_SeqList(P2);
362     Distory_SeqList(P3);
363     system("pause");
364     return 0;
365 }
366 //end Large_Number_calculator

 

 本篇文章中所有數據結構都是后期整理的,如有問題歡迎指正,轉載請注明出處http://www.cnblogs.com/a1982467767/p/8889528.html

 

實驗結果:

 

心得:

一開始,我只是按照大數相乘的思路,以順序表的形式設計了大數乘法的運算,當大數相乘算法實現了嗎,我又想設計下大數相加和相減運算,但由於一開始設計大數相減時用的是分段計算,單個大數相減運算就寫了一百多行,雖然得到的結果是正確的,但還是感覺這段代碼就是垃圾代碼,整個結構過於復雜,后來聽了老師的一些建議,我就在大數相加的基礎上修改,並通過標志位,成功完成了大數相減運算,但程序中存在BUG(在最后的大數計算器設計中發現的,經過將近兩個小時的測試,發現了錯誤的根源——兩個同等長度,前面N位基本相同,導致最后的結果沒有加上負號,使整個大數計算過程出現錯誤,最后的驗算結果不匹配)。在設計完大數加減乘之后,我想就這樣結束了,因為當時我頭腦中想象的大數想除和取余太過於復雜,但是在一次睡醒時,我腦中突然蹦出了大數相除的思想,雖然后來操作工程中存在很多問題,但還是再多次測試時候解決了(比如多次計算,內存不足,進入死循環,測試結果明顯不正確,測試結果只存在微小的錯誤,但是利用此次結果在計算時出現明顯錯誤等問題);最后設計的是大數取余運算,在前面的基礎上很輕松的就解決了;雖然最后留下來的代碼就三百多行,但實際操作過程中花費了大量的時間,不斷地修改和刪除,加總起來的代碼量也該有兩千行了,在不斷的測試過程中,我明白了結構的重要性;一開始我是用c寫的,后來覺得單純的函數操作,不如用運算符來代替,這樣看起來舒服,操作起來便捷,后來我把棧結構體寫成了棧的類,重載了運算符,雖然還是有些不明了,如果使用引用類型作為參數,着呢個結構可能會更優化點,但我還是習慣了用指針類型;美中不足的是我現在的基礎還不能實現圖形化這能將界面優化到這種程度了;

要寫好一個完整的程序,首先要設置它的結構,在結構的基礎上設置框架流程,並更具流程進行書寫,這樣會少浪費很多時間進行思考和測試,這應該就是數據結構的精髓。吧;在做完這個題目過后,我感覺我的設計思維有一定的提升,在很多困難面前,以程序員不找出Bug不睡覺的態度,真的有促進作用,這種感覺真的很棒。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM