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不睡覺的態度,真的有促進作用,這種感覺真的很棒。