C語言-大整數四則運算
阿新 • • 發佈:2019-02-12
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