第一篇博文有點小雞凍。在哈工程寒假集訓中第一次模擬中唯一一道對我有價值的題就是大數加法,隨后的幾次模擬中大數運算不斷,可見這是我們必須掌握的技能,本人智商較低,先講解下大數加法減法,乘除階乘或者結合其他知識的大數運算日后定會奉上。
究竟為什么要用大數加法呢。我們來看下數據:
bool型為布爾型,占1個字節,取值0或1。
BOOL型為int型,一般認為占4個字節,取值TRUE/FALSE/ERROR。
sbyte型為有符號8位整數,占1個字節,取值范圍在128~127之間。
bytet型為無符號16位整數,占2個字節,取值范圍在0~255之間。
short型為有符號16位整數,占2個字節,取值范圍在-32,768~32,767之間。
ushort型為無符號16位整數,占2個字節,取值范圍在0~65,535之間。
int型為有符號32位整數,占4個字節,取值范圍在-2,147,483,648~2,147,483,647之間。
uint型為無符號32位整數,占4個字節,取值范圍在0~4,294,967,295之間。
long型為64位有符號整數,占8個字節,取值范圍在9,223,372,036,854,775,808~9,223,372,036,854,775,807之間。
ulong型為64位無符號整數,占8個字節,取值范圍在0~18,446,744,073,709,551,615之間。
float型為32位單精度實數,占4個字節,取值范圍3.4E+10的負38次方~3.4E+10的38次方之間。
double型為64位實數,占8個字節,取值范圍1.7E+10的負308次方~1.7E+10的正308次方。
所以999999999999999999999999999999999999999+888888888888888888888888888888888888888888888=?
大數加法
基本思想:數組要多長有多長啊,隨便定義個a[1000000],不就OK啦!
我都能寫出來,當然代碼是非常簡單了啦,我說下要注意的幾個問題:
1. 判斷最后數組的長度
2. 去掉前導零
1 void Add(char s1[],char s2[]) //需要兩個字符串參數&&無返回值 2 { 3 int num1[M],nm2[M]; 4 int i,j; 5 len1=strlen(s1); 6 len2=strlen(s2); 7 for(i=len1-1,j=0;i>=0;i--)//num[0]保存的是低位 8 num1[j++]=s1[i]-'0'; 9 for(i=len2-1,j=0;i>=0;i--) 10 num2[j++]=s2[i]-'0'; 11 for(i=0;i<M;i++) 12 { 13 num1[i]+=num2[i]; 14 if(num1[i]>9) 15 { 16 num1[i]-=10; 17 num1[i+1]++; 18 } 19 } 20 21 for(i=M;(i>=0)&&(num1[i]==0);i--)//找到第一個不是零的數 22 { 23 if(i>=0) 24 for(;i>=0;i--) 25 printf("%d",num1[i]); 26 else 27 printf("0\n") 28 }
當然方法不止一種。如果說上面這個清晰的話,那下面這個應該是省了點內存。
1 void Add(char a[],char b[],char d[]) 2 { 3 char c[10001]; 4 int lena=strlen(a),lenb=strlen(b); 5 int i,j,len; 6 len=lena>lenb?lena:lenb; 7 len++; 8 c[0]='\0'; 9 for(i=1;i<=len;i++)c[i]='0'; 10 for(i=1;i<=lena;i++)c[i]+=a[lena-i]-48; 11 for(i=1;i<=lenb;i++)c[i]+=b[lenb-i]-48; 12 for(i=0;i<=len;i++) 13 if(c[i]>57) 14 { 15 c[i]-=10; 16 c[i+1]++; 17 } 18 19 for(i=len;i>1;i--) 20 if(c[i]==48)len--; 21 else break; 22 for(i=0;i<=len;i++) 23 d[i]=c[len-i]; 24 }
好吧,這個代碼還有個好處就是讓我記住了‘0’和‘9’的ASCII碼是48和57。
大數減法
減法的算法也是從低位開始減,先要判斷減數和被減數那一個位數長,減數位數長是正常減;被減數位數長,則被減數減減數,最后還要加上負號;兩個位數長度相等時,最好比較那一個數字大,否則負號會處理的很繁瑣;處理每一項時,如果前一位相減有錯位,就先減上一位的錯位,無則不減,再去判斷是否能夠減開被減數,如果減不開,就要借位后再去減,同時錯位為1,否則置錯位為0.
1 //d2 > d1,如果需要比較大小自己加一個不麻煩。 2 void dec(char *d1, char *d2, char *out) 3 { 4 int len_min = strlen(d1); 5 int len_max = strlen(d2); 6 int last_j = 0; //最關鍵的錯位 7 while(len_min > 0) 8 { 9 int dd1 = d1[len_min - 1] - '0'; 10 int dd2 = d2[len_max - 1] - '0'; 11 if (last_j) dd2 = dd2 - 1; 12 last_j = dd2 >= dd1 ? 0 : 1; 13 dd2 = dd2 >= dd1 ? dd2 : dd2 + 10; 14 out[len_max] = (dd2 - dd1) + '0'; 15 len_max -- ; 16 len_min -- ; 17 } 18 while(len_max > 0) 19 { 20 int dd2 = (d2[len_max -1] - '0'); 21 if (last_j) dd2 = dd2 - 1; 22 last_j = dd2 >= 0 ? 0 : 1; 23 dd2 = dd2 >= 0 ? dd2 : dd2 + 10; 24 out[len_max] = dd2 + '0'; 25 len_max --; 26 } 27 if (last_j) 28 out[0] ='1'; 29 else 30 out[0] ='0'; 31 }
哦了。就這么多了。大數乘法除法神馬的敬請期待!