20192423 2021-2022-2 《網路與系統攻防技術》實驗七實驗報告
阿新 • • 發佈:2022-05-28
高精度
題目要求:
a) 涉及知識點:陣列、流程控制、函式等
b) 要求:用整型陣列表示10進位制大整數(超過2^32的整數),陣列的每個元素儲存大整數的一位數字,實現大整數的加減法。
實現細節:
-
完全模擬簡單計算過程:讀入資料,儲存資料,處理資料,輸出資料
儲存 讀入
這裡,根據題目要求,要用整數陣列來儲存,但是介於整數陣列讀入困難的問題,應該使用字串來處理輸入,然後再對字串就行處理輸入到整數陣列中,讀入字串時,數字最高位在字串首(下標小的位置)。但是習慣上,下標最小的位置存放的是數字的 最低位,即儲存反轉的字串。例下圖輸入15604121072時,先儲存進char陣列中,採用字串讀取,然後反轉處理成整數儲存在整數陣列中。
程式碼實現:
void read(int a[]) { static char s[LEN + 1]; //靜態 scanf("%s", s); clear(a); int len = strlen(s); // 反轉 for (int i = 0; i < len; ++i) a[len - i - 1] = s[i] - '0'; // 字元轉數字 }
輸出
從後向前找不為零的數,然後按位依次輸出即可
void print(int a[]) { int i; for (i=LEN-1;i>=1;--i) //這裡判定不能限定為i>=0;這樣的話執行完i=-1,會導致無輸出 if (a[i] != 0) break; for (; i>=0;--i) putchar(a[i] + '0'); putchar('\n'); }
加法:
按照豎式加法,從最低位開始,將兩個加數對應位置上的數值相加,並判斷是否達到或超過10 。如果達到,那麼處理進位:將更高一位的結果上增加 1,當前位的結果減少10 。(可以考慮取模,和除法,但是不可能出現大於18的情況,所以沒必要)
本題所設定的最大位數為LEN=1000位,但一般令陣列的最大長度 LEN 比可能的輸入大一些, 然後略去末尾的幾次迴圈,可以省去不少邊界情況的處理,故在此迴圈到 LEN - 1 = 1003 已經足夠
程式碼:
void add(int a[], int b[], int c[]) { clear(c); for (int i = 0; i < LEN - 1; ++i) { c[i]+=a[i]+b[i]; // 將相應位上的數碼相加 if (c[i] >= 10) { c[i + 1]+=1; c[i]-=10; } } }
減法:
判定:先判定前面是否大於後面,如果不大於就換位,同時在前面加負號,
首先判斷位數,位數大的大,然後相等時從最高位向低位判斷,如果對應位後大於前,說明傳入的第一個數比第二個數小,直接結束.
int judge(int a[],int b[]){ int i,j,k; //分別最大位 for(i=LEN-1; i>=0;--i) if(a[i]!=0) break; for(j=LEN-1; j>=0; --j) if(b[j] != 0) break; //分別判斷 if(i < j) return 0; else if(i>j) return 1; for(; i>= 0;--i){ if(a[i]<b[i]) return 0; } return 1; }
實現:從個位起逐位相減,遇到負的情況則向上一位借 1。
void sub(int a[], int b[], int c[]) { clear(c); for (int i=0; i<LEN-1; ++i) { c[i]+=a[i] - b[i]; // 逐位相減 if (c[i]< 0) { c[i+1]-=1; c[i]+=10; } } }
實現程式:
#include<bits/stdc++.h> static const int LEN = 1004; int a[LEN], b[LEN], c[LEN]; void clear(int a[]) { for (int i=0; i<LEN; ++i) a[i] = 0; } void read(int a[]) { static char s[LEN + 1]; //靜態 scanf("%s", s); clear(a); int len = strlen(s); // 反轉 for (int i=0; i<len; ++i) a[len - i - 1] = s[i] - '0'; // s[i] - '0' 就是 s[i] 所表示的數值 } void print(int a[]) { int i; for (i=LEN-1;i>=1;--i) //這裡判定不能限定為i>=0;這樣的話執行完i=-1,會導致無輸出 if (a[i] != 0) break; for (; i>=0;--i) putchar(a[i] + '0'); putchar('\n'); } int judge(int a[],int b[]){ int i,j,k; //分別最大位 for(i=LEN-1; i>=0;--i) if(a[i]!=0) break; for(j=LEN-1; j>=0; --j) if(b[j] != 0) break; //分別判斷 if(i < j) return 0; else if(i>j) return 1; for(; i>= 0;--i){ if(a[i]<b[i]) return 0; } return 1; } void add(int a[], int b[], int c[]) { clear(c); for (int i = 0; i < LEN - 1; ++i) { c[i]+=a[i]+b[i]; // 將相應位上的數碼相加 if (c[i] >= 10) { c[i + 1]+=1; c[i]-=10; } } } void sub(int a[], int b[], int c[]) { clear(c); for (int i=0;i<LEN-1;++i) { c[i]+=a[i]-b[i]; // 逐位相減 if (c[i]<0) { c[i+1]-=1; c[i]+=10; } } } int main() { printf("Please make sure the first num is larger than the second.\nAnd make sure the maximum number of digits is 1000 \n"); read(a); read(b); printf(" the result of add is: "); add(a, b, c); print(c); printf(" the result of sub is: "); if(judge(a,b)) sub(a,b,c); else { putchar('-'); sub(b,a,c);} print(c); return 0; }
d單精度乘法
實現時注意得兩個for迴圈分別判斷,要不然前面進位會對結果產生影響導致錯誤
void mul(int a[],int e){ for(int j=0;j<MAX;j++) b[j] *=e; for(int j=0;j<MAX;j++) if(b[j]>9){ b[j+1]+=b[j]/10; b[j]%=10; } }