1. 程式人生 > >C語言-大整數四則運算

C語言-大整數四則運算

int的儲存空間有限,利用”串”的結構,分享一則“大整數”簡單四則運算。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct bigint
{
    char *num;                //指向長整數陣列(序號0中儲存著最高位) 
    char minus;               //符號(1表示正數,-1表示負數) 
    int digit;                 //儲存該數的位數(實際位數) 
}BIGINT, *pBIGINT; 

void
BigIntTrans(pBIGINT num1) //將字串轉為數字表示 { char *temp; //臨時陣列 int i,k,len; len=strlen(num1->num); //字串長度 //分配記憶體 if(!(temp = (char *)malloc(sizeof(char)* len))) { printf("記憶體分配失敗!\n"); exit(0); } i=0; num1->minus=1
; //儲存為正數 if(num1->num[0]=='-') //判斷是否為負數 { num1->minus=-1; i++; } k=0; //數字位數計數器 while(num1->num[i]!='\0') //字串未結束 { if(num1->num[i]>='0' && num1->num[i] <='9') //數字為0~9 //將ASCII碼轉換為對應數字
temp[k]=num1->num[i]-'0'; k++; } i++; } for(i=0;i<num1->digit;i++) //清空陣列各元素 num1->num[i]=0; num1->digit=k; //轉換後的資料位數 for(i=0,k--;k>=0;k--,i++) //將臨時陣列各位置反置儲存到陣列num中 num1->num[i]=temp[k]; BigIntTrim(num1); //整理輸入的大整數 } void BigIntTrim(pBIGINT num1) //整理大整數,去掉前面多餘的0 { int i; for(i=num1->digit-1;i>=0;i--) //從高位檢查是否為0 { if(num1->num[i] !=0) //遇到不為0的最高位 break; //跳出迴圈 } if(i<0) //若餘數全部為0 { num1->digit=1; //設定餘數位數為1 num1->num[0]=0; }else num1->digit=i+1; //餘數位數 } void BigIntPrint(pBIGINT result) //輸出大整數 { int j; if(result->minus ==-1) //是負數 printf("-"); //輸出負數 //若大整數為0 if(result->digit ==1 &&result->num[0]==0) printf("0"); else //不為0 { //從高位到低位輸出 for(j=result->digit-1;j>=0;j--) printf("%d",result->num[j]); } } int BigIntEqual(pBIGINT num1,pBIGINT num2) //比較絕對值大小 { int i; //num1的位數大於num2 if(num1->digit>num2->digit) return 1; //num1的位數小於num2 else if(num1->digit<num2->digit) return -1; else //兩數位數相等 { i=num1->digit-1; //num1的資料位數 while(i>=0) //從高位向地位比 { //num1對應位大於num2 if(num1->num[i]>num2->num[i]) return 1; //num1對應位小於num2 else if(num1->num[i]<num2->num[i]) return -1; else //比較下一位 i--; } } return 0; //相等 } void BigIntAdd(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i; i=BigIntEqual(num1,num2); //比較兩數絕對值大小 if(i<0) //num1絕對值小於num2 { pBIGINT temp; temp=num1; //交換兩數 num1=num2; num2=temp; } if(num1->minus * num2->minus <0) //符號不同,則執減法 { if(i==0) //兩數相等 { //結果長度為一位數,就是數值0 result->digit =1; result->num[0]=0; //結果值為0 result->minus =1; //結果設為正號 return; //返回 } //呼叫相減函式完成異號相加 BigIntSub1(num1,num2,result); }else //呼叫相加函式完成同號相加 BigIntAdd1(num1,num2,result); } void BigIntAdd1(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i,carry; carry=0; //清除進位 result->minus =num1->minus; //儲存符號 //將被加數複製到結果陣列中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; //num2中的數小,可能位數也少些 for(i=0;i<num2->digit;i++) { //將對應位的數和進位數相加 result->num[i]=result->num[i]+num2->num[i]+carry; carry=result->num[i]/10; //計算進位資料 result->num[i]=result->num[i]%10; //保留一位 } if(carry) //若最後還有進位 result->num[i]=result->num[i]+carry; BigIntTrim(result); //整理結果 } //減法函式 void BigIntSub(pBIGINT num1,pBIGINT num2,pBIGINT result) { num2->minus =-1 * num2 ->minus; //將減數的符號取反 BigIntAdd(num1,num2,result); //呼叫加法函式 } //異號相減函式 void BigIntSub1(pBIGINT num1,pBIGINT num2,pBIGINT result) { int i,borrow; result->minus =num1->minus; //結果符號 borrow=0; //將被減數的內容複製到結果中 for(i=0;i<num1->digit;i++) result->num[i]=num1->num[i]; for(i=0;i<=num2->digit;i++) { //num1減去num2,並減去低位的借位 result->num[i]=result->num[i]-num2->num[i]-borrow; if(result ->num[i]<0) //若為負數 { result->num[i]=10+result->num[i]; //向高位借位 borrow=1; //設定借位數 }else borrow=0; } if(borrow==1) result->num[i]=result->num[i]-borrow; i=num1->digit; while(i>0) { if(result->num[i]==0) i--; else break; } result->digit=i+1; //儲存結果位數 BigIntTrim(result); //整理結果 } void BigIntMul(pBIGINT num1,pBIGINT num2,pBIGINT result) { char carry,temp; int i,j,pos; //結果陣列和中間數清0 for(i=0;i<num1->digit+num2->digit;i++) result->num[i]=0; //用乘數的每一位乘以被乘數 for(i=0;i<num2->digit;i++) { carry=0; //清除進位 //被乘數的每一位 for(j=0;j<num1->digit;j++) { //相乘並加上進位 temp=num2->num[i] * num1->num[j]+carry; //計算進位carry carry =temp/10; //計算當前位的值 temp=temp%10; pos=i+j; //計算結果累加到臨時陣列中 result->num[pos]+=temp; carry=carry+result->num[pos]/10; //計算進位 result->num[pos]=result->num[pos]%10; } if(carry>0) { result->num[i+j]=carry; //加上最高位進位 result->digit=i+j+1; //儲存結果位數 }else result->digit=i+j; //儲存結果位數 } result->minus=num1->minus * num2->minus; //結果的符號 } void BigIntDiv(pBIGINT num1,pBIGINT num2,pBIGINT result,pBIGINT residue) //除法函式 { BIGINT quo1,residol,quo2; int i,j,k,m; //k儲存試商結果,m儲存商的位數 char t; result->minus = num1->minus * num2->minus; //商的符號 //分配餘數的記憶體空間 residue->num =(char *)malloc(sizeof(char) * num2->digit); for(i=0;i<residue->digit;i++) //將餘數全部清0 residue->num[i]=0; m=0; for(i=num1->digit-1;i>=0;i--) { //重新設定餘數的位數比除數多一位 residue->digit=num2->digit+1; for(j=num2->digit-1;j>0;j--) //移餘數 residue->num[j]=residue->num[j-1]; //複製被除數中的一位到餘數的最低位中 residue->num[0]=num1->num[i]; BigIntTrim(residue); //整理餘數 k=0; //試商 //比較餘數與除數的大小 while(BigIntEqual(residue,num2)>=0) { BigIntSub1(residue,num2,residue); //用餘數減去除數,差值儲存在餘數中 k++; //試商加1 } result->num[m++]=k; //儲存商 } result->digit=m; //儲存商的位數 for(i=0;i<m/2;i++) //反轉商的值 { t=result->num[i]; result->num[i]=result->num[m-1-i]; result->num[m-1-i]=t; } BigIntTrim(result); //整理商 BigIntTrim(residue); //整理餘數 } int main() { //參與運算的數,結果,餘數 BIGINT num1,num2,result,residue; int i=0,len; char op; printf("輸入最大數的位數:"); scanf("%d",&len); if(!(num1.num=(char *)malloc(sizeof(char) * (len+1))) ) { printf("記憶體分配失敗!\n"); exit(0); } num1.digit=len +1; if(!(num2.num=(char *)malloc(sizeof(char) * (len +1)))) { printf("記憶體分配失敗!\n"); exit(0); } num2.digit=len+1; if(!(result.num=(char *)malloc(sizeof(char) * (2*len +1)))) { printf("記憶體分配失敗!\n"); exit(0); } result.digit=2*len+1; for(i=0;i<result.digit;i++) //清空結果集 result.num[i]=0; printf("選擇大整數的運算(+,-,*,/):"); fflush(stdin); scanf("%c",&op); switch(op) { case '+': printf("\n輸入被加數:"); scanf("%s",num1.num); printf("\n輸入加數:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntAdd(&num1,&num2,&result); //加法 break; case '-': printf("\n輸入被減數:"); scanf("%s",num1.num); printf("\n輸入減數:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntSub(&num1,&num2,&result); //減法 break; case '*': printf("\n輸入被乘數:"); scanf("%s",num1.num); printf("\n輸入乘數:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); BigIntMul(&num1,&num2,&result); //乘法 break; case '/': printf("\n輸入被除數:"); scanf("%s",num1.num); printf("\n輸入除數:"); scanf("%s",num2.num); BigIntTrans(&num1); BigIntTrans(&num2); if(num2.digit==1 && num2.num[0]==0) //大整數為0 printf("除數不能為0!\n"); else BigIntDiv(&num1,&num2,&result,&residue); //除法 break; } if(op=='/') { //為除法且除數不為0 if(!(num2.digit==1 && num2.num[0]==0)) { printf("商:"); BigIntPrint(&result); printf("\t餘數:"); BigIntPrint(&residue); } }else { printf("結果:"); BigIntPrint(&result); } getch(); return 0; }

資源下載位置:

歡迎關注我的微信個人訂閱號
這裡寫圖片描述
每天多學一點0.0