最大公約數(大數版)
阿新 • • 發佈:2019-02-14
示例:
99999999999999999999(20位) 與 6666666666666666666(20位): gcd= 33333333333333333333(20位)
思路:全部寫在註釋裡面了~
/*********************************************************** FileName: 大數最大公約數(位移版).cpp Author: Dojking Version : V1.0 Date:2014/3/16 Function List: 1.int main() 主函式 2.void strmod(); 模擬大數取餘 3.void strsub(); 模擬大數減法 History: <author> <time> <version > <desc> Dojking 2014/3/16 1.0 build ***********************************************************/ #include <iostream> #include <string> using namespace std; int pos, zero, len1, len2;/*pos:匹配位置,zero:str1高位最後一個0的位置,len1:str1長度,len2:str2長度*/ string str1, str2, mod; /*str1:大數1,str2:大數2,mod:每步的餘數*/ /******************************************************************************************************** strsub()函式: 模擬大數快速減法,末尾補0法雖然能快速的做減法,然後由於是字串操作,末尾減0的操作實際上是無用的操作。 這裡引入位移法,進行快速減法。 具體思想:(假設str1 > str2)我們先比較str1[0],str2[0]值得大小,用以確定str2與str1的匹配位置。 比如:str1=12345678 , str2=431,由於str1[0] < str2[0],所以應當這樣匹配做減法: str1: 12345678 str2: 431 又如:str1=5173 , str2=29,由於str1[0] > str2[0],所以應當這樣匹配做減法: str1: 5173 str2: 29 同時,直接在str1裡面儲存減好的值。並且用str2的長度控制減法的次數。 ********************************************************************************************************/ void strsub() /*該函式用大數減法,模擬取餘*/ { int i,j; pos = zero+1; /*pos指向str1有效位的第一位*/ if (str1[pos] < str2[0])/*如果str1[pos] < str2[0],說明不能從最高位開始減。如123 - 45也不能從最高位開始減*/ { ++pos; /*後移一位*/ } for (i=pos+len2-1,j=len2-1; j >= 0; --i,--j) /*模擬減法*/ { if (str1[i] < str2[j] || str1[i] == 'f') /*需要借位,f表示-1*/ { if (str1[i-1] != '0') /*高位不為0*/ { str1[i-1] -= 1; /*向高位借位*/ } else /*高位為0,借位後變為-1,用f表示-1*/ { str1[i-1] = 'f'; /* f = -1 */ } if (str1[i] == 'f') /*本位為f,直接用-1代替*/ str1[i] = ((-1+10)-(str2[j]-'0')+'0'); else /*本位不為f,執行 '-' 操作*/ str1[i] = ((str1[i]-'0')+10-(str2[j]-'0')+'0'); } else /*不需要借位,直接 '-' 操作*/ { str1[i] = ((str1[i]-'0')-(str2[j]-'0')+'0'); } } while (str1[zero+1] == '0' && (len1-zero) != 2) /*去掉相減後高位上的無效0。(len1-zero) != 2:防止全為0的情況)*/ { ++zero; } } /**************************************************************************** strmod()函式: 主要負責一些值的初始化,捨去str1高位上的無效0,和當str1 < str2時跳出迴圈。 ****************************************************************************/ void strmod() /*此函式作用相當於 str1 %= str2,注意str1,str2都是全域性變數*/ { zero = -1; /*zero指向當前高位上最後一個0的位置*/ len1 = str1.size(); /*獲得串長度*/ len2 = str2.size(); /*如果str1 < str2,則跳出。注意字串模擬數字大小比較,同時str1前面可能有多餘的0*/ while (! (len1 - (zero+1) < len2 || str1[zero+1] < str2[0] && (len1 - (zero + 1) <= len2)) ) { strsub(); /*進行大數減法,模擬取餘*/ } mod = ""; /*重置mod,避免對下面的mod+=造成影響*/ while (zero < len1-1) /*捨去str1高位上的0,將有效數字拷貝進mod,傳進main函式,進行下次輾轉*/ { mod += str1[++zero]; } } /**************************************************************************************** main()函式: 主函式,函式中省去了,swap()函式,因為不管是str1>str2,還是str1<str2都不影響執行結果。 分析:如果str1 < str2。程式執行到strmod()中將不進入while(1),然後返回main()函式。 在main()-while()中交換了str1,str2的值。 同時,主函式中增加了一個迴圈函式,便於測試多組資料,而不是執行一次只能測試一組資料。 ****************************************************************************************/ int main() { while (1) /*便於測試多組資料*/ { cin>>str1>>str2; /*輸入兩個大數*/ if (str1[0] == '0' || str2[0] == '0') /*請不要輸入0*/ { cout<<"input error"<<endl; break; } while (str2[0] != '0') /*大數取餘運算跳出條件*/ { strmod(); /*此函式作用相當於 str1 %= str2,注意str1,str2都是全域性變數*/ str1 = str2; /*str1儲存較大數*/ str2 = mod; /*str2儲存餘數*/ } cout<<str1<<endl; /*輸出求餘結果*/ } return 0; }