大樹乘法(C/C++實現)
#include<stdio.h> #include<stdlib.h> #include<iostream> #include <string.h> //strlen(x)必要,而不是<string> using namespace std; int main() { char x[99999]; char y[99999]; char z[99999];//存放每次乘法結果 char z_all[99999]; //存放加起來的結果 char big[99999];//存放x[]和y[]更大的那個陣列 ,相當於列式計算的上面那個數 char small[99999];//存放x[]和y[]更小的那個陣列 ,相當於列式計算的下面那個數 int multi=0;//2個數相乘得到的 int count=0;//乘法進位的數 int length=0;//用於計算z[]的長度 int length_all=0; //用於計算z_all[]的長度,很難搞,因為ascii0代表為\0,所以strlen(z_all)沒用,length_all=length或者length+1或-1 int plus=0;//2個數相加得到的 int count_z=0;//加法進位的數 scanf("%s",&x); scanf("%s",&y); int x_length=strlen(x); int big_length=0;//記錄x_length和y_length更大的長度為 int y_length=strlen(y); int small_length=0;//記錄x_length和y_length更小的長度為 //1,判斷x[]和y[]誰更長,得到長度,並把更長的放入big[],更短的放入small[] //2,每一位都-48,才可以開始計算。 if(x_length>y_length) { big_length=x_length; small_length=y_length; for(int i=0;i<(big_length);i++) { big[i]=x[i]-48; if(i<y_length) small[i]=y[i]-48; else small[i]=0; } } else { big_length=y_length; small_length=x_length; for(int i=0;i<(big_length);i++) { big[i]=y[i]-48; if(i<x_length) small[i]=x[i]-48; else small[i]=0; } } //字串逆轉strrev(),不能用這個函式,和strlen()一樣,碰ascii0結束 //strrev(big); int num=big_length/2; int first_num=0;//執行字串逆轉的 for(int i=0;i<num;i++) { first_num=big[i]; big[i]=big[big_length-1-i]; big[big_length-1-i]=first_num; } //strrev(small); num=small_length/2; for(int i=0;i<num;i++) { first_num=small[i]; small[i]=small[small_length-1-i]; small[small_length-1-i]=first_num; } //--------------------計算每次結果,並執行加法,得到總結果 for(int i=0;i<small_length;i++) { memset(z, 0, sizeof(z));//用完陣列一定要記得情空 count=0; length=0; for(int j=0;j<big_length;j++) { multi=small[i]*big[j]+count; if(multi<10) { count=0; } else count=multi/10; z[j]=multi%10; length++; //每次運算結果的第一位可能需要進位 if(j==big_length-1) { if(multi>=10) { length++; z[j+1]=multi/10; } count=0; //運算完了之後進位為0 } } //逆轉每次運算結果再加上根據正在計算small[]中第幾個數決定末尾的0,真正的每次運算結果 //strrev(z);//字串逆轉 num=length/2; for(int m=0;m<num;m++) { first_num=z[m]; z[m]=z[length-1-m]; z[length-1-m]=first_num; } //根據正在計算small[]中第幾個數決定末尾的0,真正的每次運算結果 for(int m=0;m<i;m++) { z[length]=0; length++; } //在每次 執行z_all[]和z[] 的加法 之前先對z_all[]補充到和z[]一樣的位數 //可能補充1位,可能補充2位 if(length_all==length) ; else { //1 是 -1,2是+0,3是+1 ,4是 +2,相差2 //觀察得到 length-length_all-2 是 for(int m=length+(length-length_all-2);m>=length-length_all;m--) { z_all[m]=z_all[m-(length-length_all)]; } for(int m=0;m<length-length_all;m++) { z_all[m]=0; } length_all=length; } //加起來存放在z_all[],執行z_all[]和z[] 的加法 for(int m=(length-1);m>=0;m--) { plus=z[m]+z_all[m]+count_z; if(plus>=10) { count_z=1; z_all[m]=plus%10; //每次運算結果的第一位可能需要進位 if(m==0) { count_z=0; //必須這樣寫,不然strlen()以\0結束,而ascii的0就是\0 length_all=length+1; for(int n=length;n>0;n--) { z_all[n]=z_all[n-1]; } z_all[0]=1; } } else { z_all[m]=plus; count_z=0; } } } //--------------------得到總結果 //還原成char[],才可以用字串%s顯示出來,不然可能要一個一個%d輸出 for(int i=0;i<length_all;i++) { z_all[i]+=48; } printf("總結果為%s",z_all); system("pause"); }
190行的程式碼,測試用例 99999 888 答案是88799112
456456 123 答案是56144088
測試輸入的2個大數含有0,導致z_all[]有0,z[]有0 5002 1005 答案是5027010
測試先輸入的數更小 5153135 561523152315615615614 答案是2893604609507929875367049890
執行加法的時候,z_all[]肯定小於等於z[]的位數,但是可能相差2位 測試z_all[]和z[]相差2位會不會出錯 890749640310 50438001 答案44927631248705420310
測試很大的數 90651132051212022320006511320512120223200132051212022313205121202232000651132051212013205121202232000651132051212013205121202232000651132051212013205121202232000651132051212020006511320512121320512120223200065113205121200223200065113205121201320512120132051212022320006511320512120132051212022320006511320512120 90651132051212022320006511320512120223200132051212022313205121202232000651132051212013205121202232000651132051212013205121202232000651132051212013205121202232000651132051212020006511320512121320512120223200065113205121200223200065113205121201320512120132051212022320006511320512120132051212022320006511320512120
答案是 8217627742166279593258384227255322134089168057783095489827406231962126915594425136982130897336827272053686532782672814722755608909707178267744737424004508273738713256092706803266393688426607267974586188598208659424356181871486133193036707046839862429341995222708292917387307560071705279510878182313569177763680001920799585684429461042518936481023593237602722809931476763334431426660612680265603460144823480818435663628168450038546990715014132411802891692469338365699322791894396940981129039967003179268156321618886806960655095730601018201634939432173224868109964974975399259786821141967502182478768938331611554659066894400
1,strlen()和strrev()不能對char[]存放數字0進行操作,因為ascii0就是字元\0,需要自己實現strlen()和strrev()