- 论坛徽章:
- 1
|
没事编着玩儿,有兴趣的共同交流。
/***************************************
程序名L无符号大数的四则去处程序
---------------------------------------------------
程序设计:飘来飘去的云
编制语言:标准C
编制时间:2013-5-18
****************************************/
#include <stdio.h>
#include <string.h>
#define MAX_DIGITAL 1024
/********************************************
大数加前零
*********************************************/
char *add0BigNum(unsigned char *a,int n)
{
int i,len;
len=strlen(a);
a[len+n]=0;
for (i=len; i>0; i--)
{
a[i-1+n]=a[i-1];
}
for (i=0; i<n; i++) a[i]='0';
return a;
}
/********************************************
大数去前零
*********************************************/
char *trimBigNum(unsigned char *a)
{
int i,j,k;
k=0;
for (i=0; i<strlen(a); i++)
{
if (a[i]=='0')
{
k++;
}
else
{
for (j=i; j<=strlen(a); j++)
{
a[j-k]=a[j];
}
return a;
}
}
a[0]='0';a[1]=0; //全部为'0'的串
return a;
}
/********************************************
大数比较,a,b
返回,a>b >0
a=b =0
a<b <0
*********************************************/
int BigNum_Comp(unsigned char *a,unsigned char *b)
{
trimBigNum(a);
trimBigNum(b);
if (strlen(a)>strlen(b)) return 11;
if (strlen(a)<strlen(b)) return -11;
return strcmp(a,b);
}
/*********************************************************************
两个无符号大数相乘法
参数说明:a,b 两个乘数 结果存放于c中
a,b,c均为ASCII字符串(数字),结果可以回存于到乘数数组中
**********************************************************************/
char *Bignum_Mul(unsigned char *a,unsigned char *b,unsigned char *r)
{
unsigned char r1[MAX_DIGITAL*2];
int i,j,la,lb,t1,t2;
la=strlen(a);lb=strlen(b);
for (i=0; i<la+lb; i++) r1[i]=0; //结果数组初始化
for (i=lb-1; i>=0; i--)
{
for (j=la-1; j>=0; j--)
{
t1=r1[i+j+1]+(a[j]-'0')*(b[i]-'0');
r1[i+j+1]=(t1 % 10);
r1[i+j] += t1 / 10;
}
}
j=0;
for (i=0; i<la+lb; i++)
{
r1[i]=r1[i]+'0';
}
r1[i+j]=0;
trimBigNum(r1);
strcpy(r,r1);
return r;
}
/*********************************************************************
两个无符号大数相除法
参数说明:a,b 被除数,除数 结果存放于c中,余数存放于r中
a,b,c均为ASCII字符串(数字),结果可以回存于到乘数数组中
**********************************************************************/
char *Bignum_Div(unsigned char *a,unsigned char *b,unsigned char *c,unsigned char *r)
{
unsigned char result[MAX_DIGITAL],remain[MAX_DIGITAL];
int i,j,l,la,lb,n;
i=BigNum_Comp(a,b);
if ( i == 0) //两数相等,结果为1,余数为0
{
c[0]='1';c[1]=0;
r[0]='0';r[1]=0;
return c;
}
if ( i < 0) //如果被除数小,余数就直接等于被除数
{
strcpy(r,a);
c[0]='0';c[1]=0;
return c;
}
for (i=0; i<MAX_DIGITAL; i++) //结果初始化
{
result[i]=remain[i]=0;
}
la=strlen(a);lb=strlen(b); //la >= lb
strncpy(remain,a,lb);
i=0; //结果位指针
j=lb; //运算指针,指示当前算到被除数的哪一位了
while(1)
{
n=0;
while(BigNum_Comp(remain,b)>0)
{
Bignum_Min(remain,b,remain);
n++;
}
result[i]=n+'0';
i++;
if (a[j] == 0)
{
break;
}
l=strlen(remain);remain[l]=a[j];remain[l+1]=0; //右移一位
j++;
}
result[i]=0;
strcpy(c,result);
trimBigNum(remain);
strcpy(r,remain);
return r;
}
/*********************************************************************
两个无符号大数加法
参数说明:a,b 两个加数 结果存放于c中
a,b,c均为ASCII字符串(数字),结果可以回存于到加数数组中
**********************************************************************/
char *Bignum_Add(unsigned char *a,unsigned char *b,unsigned char *r)
{
unsigned char r1[MAX_DIGITAL],*ch;
int i,j,la,lb,lr,t1;
la=strlen(a);lb=strlen(b);
if (la < lb)
{
ch=a;a=b;b=ch; //保证a位长不小于b
}
la=strlen(a);lb=strlen(b);
lr=la+1;
for (i=0; i<lr; i++) r1[i]=0; //结果数组初始化
t1=0;
for (i=la-1; i>=0; i--) //i为长数的下标
{
j=i-(la-lb); //j为短数的下标
if (j >=0)
{
t1=(a[i]-'0')+(b[j]-'0')+t1;
}
else
t1=a[i]-'0'+t1;
r1[i+1]=t1 %10 +'0';
t1/=10;
}
if (t1) r1[0]='1'; else r1[0]='0';
r1[lr+1]=0;
trimBigNum(r1);
strcpy(r,r1);
return r;
}
/*********************************************************************
两个无符号大数减法
参数说明:a,b 被减数,减数 结果存放于c中
a,b,c均为ASCII字符串(数字),结果可以回存于到加数数组中
返回int,a>b:1; a=b:0 a<b:-1
**********************************************************************/
int Bignum_Min(unsigned char *a,unsigned char *b,unsigned char *r)
{
unsigned char r1[MAX_DIGITAL],*ch;
int i,j,la,lb,lr,t1,k,flag;
flag=BigNum_Comp(a,b);
if (!flag ) //两数相等,直接返回结果0
{
r[0]='0';r[1]=0;
return 0;
}
if ( flag<0 )
{
ch=a;a=b;b=ch; //保证a不小于b,运算结果为正数
}
la=strlen(a);lb=strlen(b);
lr=la;
for (i=0; i<lr+1; i++) r1[i]=0; //结果数组初始化
k=0; //借位标志
for (i=la-1; i>=0; i--) //i为长数的下标
{
j=i-(la-lb); //j为短数的下标
if (j >=0)
{
if (a[i] < (b[j]+k)) //不够减,需要借位
{
t1=10+(a[i]-'0')-(b[j]-'0')-k;
k=1;
}
else
{
t1=(a[i]-'0')-(b[j]-'0')-k;
k=0;
}
}
else
if (a[i] < k) //不够减,需要借位
{
t1=10+(a[i]-'0')-k;
k=1;
}
else
{
t1=(a[i]-'0')-k;
k=0;
}
r1[i]=t1+'0';
}
trimBigNum(r1);
strcpy(r,r1);
return flag;
}
int main(int argc, char *argv[])
{
unsigned char *a="9835636787334143566568710547243798",*b="100050000000",c[MAX_DIGITAL*2],d[MAX_DIGITAL];
Bignum_Div(a,b,c,d);
printf("%s\t%s\n%s\t\t\t%s\n",a,b,c,d);
return 0;
}
|
|