大数处理

 

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

char c[2000];//全局变量,存储大数运算的结果
char arr[1000];//高精度除以高精度的余数
long z=0;//高精度除以低精度的余数

int Judge(char ch[])
{//判断字符串ch是否全为,若全为,返回,否则返回
 int i,k;
 k=strlen(ch);

 for(i=0;i<k;i++)
  if(ch[i]!='0')
   return 0;
 return 1;
}

int Compare(char a[],char b[])
{//比较字符串的大小,方法不同于strcmp函数,类似于整型常量的比较
 int lena,lenb,i;

 lena=strlen(a);
 lenb=strlen(b);

 if(lena<lenb)
  return -1;
 else if(lena>lenb)
  return 1;
 else
 {
  if(strcmp(a,b)==0)
   return 0;
  else
  {
   for(i=0;i<lena;i++)
   {
    if(a[i]>b[i])
     return 1;
    if(a[i]<b[i])
     return -1;
   }
   return 0;
  }
 }
}

/*算法:先确定a和b中的最大位数k,然后依照由低至高位的顺序进行加法运算。
注意进位,若高位有进位,则c的长度为k+1。*/
//高精度加法
void BigNumberAdd(char a1[],char b1[])
{
 int i,j,k,lena,lenb;
 int a[1000]={0},b[1000]={0},d[1000]={0};

 lena=strlen(a1);
 lenb=strlen(b1);

 //将加数与被加数化为整型数组,并且该数组的其他位为0
 for(i=0;i<lena;i++)
  a[i]=a1[lena-i-1]-'0';
 for(i=0;i<lenb;i++)
  b[i]=b1[lenb-1-i]-'0';

 //当数组除了加数和被加数以外的整型数组元素均为时,无需考虑lena和lenb的大小
 k=lena>lenb?lena:lenb;
 for(i=0;i<k;i++)
 {
  d[i]=a[i]+b[i]+d[i];
  d[i+1]=d[i+1]+d[i]/10;
  d[i]=d[i]%10;
 }
 //若高位进
 while(d[k])
  k++;
 while(!d[k-1])
  k--;//001+0003=4
 //将整型数组逆着转变并赋值给c字符型数组
 for(j=0;j<k;j++)
  c[j]=d[k-j-1]+'0';
 if(Judge(c))//若全为,则只输出一个
  strcpy(c,"0");
}

/*算法:依照由低位至高位的顺序进行减法运算。在每次位运算中,
若出现不够减的情况,则向高位借位。在进行了la的减法后,若最高
位为,则a的长度减。若A、B大小未知,则需先判断大小。*/
//高精度减法
void BigNumberSub(char a1[],char b1[])
{//a1为被减数,b1为减数
 int lena,lenb,i,j,k,flag;
 int a[1000]={0},b[1000]={0},d[1000]={0};

 lena=strlen(a1);
 lenb=strlen(b1);
 if(Compare(a1,b1)>=0)
 {//若被减数大于等于减数
  for(i=0;i<lena;i++)
   a[i]=a1[lena-1-i]-'0';
  for(i=0;i<lenb;i++)
   b[i]=b1[lenb-1-i]-'0';
  flag=0;//结果正的标志
 }
 else
 {//若被减数小于减数
  for(i=0;i<lenb;i++)
   a[i]=b1[lenb-1-i]-'0';
  for(i=0;i<lena;i++)
   b[i]=a1[lena-1-i]-'0';
  flag=1;//结果负的标志
 }

 k=lena>lenb?lena:lenb;
 for(i=0;i<k;i++)
 {//大数减小数
  if(a[i]<b[i])
  {//若被减数不够减,向高位借一位
   a[i+1]--;
   d[i]=a[i]-b[i]+10;
  }
  else
   d[i]=a[i]-b[i];
 }
 //若较高位已为,并且不止位时
 while(!d[i-1])
 {
  k--;
  i--;
 }
 //根据flag,输出有无"-"
 if(!flag)
 {
  for(i=0;i<k;i++)
  {//将结果转化为字符逆着赋给数组c
   if(!i&&!d[k-i-1])//若差的第一个字母为,则马上跳过
    continue;
   c[i]=d[k-i-1]+'0';
  }
 }
 else
 {
  c[0]='-';
  for(i=1;i<=k;i++)
  {//将结果转化为字符逆着赋给数组c
   if(i==1&&!d[k-i])//若差的第一个字母为,则马上跳过
    continue;
   c[i]=d[k-i]+'0';//注意d的下标,不是k-i-1
  }
 }
 if(Judge(c))//若差全为,则只输出一个
  strcpy(c,"0");
}

/*算法:将多位数存入数组,低位在前、高位在后,
然后用一位数去乘数组的各位,考虑进位,最后按正常顺序输出*/
//高精度乘法--高精度乘以低精度
void BigNumMultiSmall(char a1[],int b1)
{
 int i,j,t;
 int a[2000]={0};
 //将字符串转化为整型数组,并逆置
 t=strlen(a1);
 for(i=0;i<t;i++)
  a[i]=a1[t-1-i]-'0';
 //整型数组的每个元素乘以b1,然后对其进行求余,整除,使其只有一位数
 a[0]=a[0]*b1;
 for(i=1;i<t;i++)
 {
  a[i]*=b1;
  a[i]+=a[i-1]/10;
  a[i-1]=a[i-1]%10;
 }
 while(a[i-1]>9)
 {//若最后一个元素大于
  a[i]=a[i-1]/10;
  a[i-1]=a[i-1]%10;
  i++;
 }
 //将得到的整型数组逆置赋给字符串
 for(j=0;j<i;j++)
  c[j]=a[i-j-1]+'0';
 if(Judge(c))//若积全为,则只输出一个
  strcpy(c,"0");
}

//高精度乘法--高精度乘以高精度
void BigNumMultiBig(char a1[],char b1[])
{
 int i,j,k,lena,lenb;
 int a[1000]={0},b[1000]={0},d[2000]={0};
 //将字符串转化为整型数组,并逆置
 lena=strlen(a1);
 lenb=strlen(b1);
 for(i=0;i<lena;i++)
  a[i]=a1[lena-i-1]-'0';
 for(i=0;i<lenb;i++)
  b[i]=b1[lenb-i-1]-'0';
 //计算乘数从低位到高位以此乘以被乘数的低位到高位
 for(i=0;i<lena;i++)
  for(j=0;j<lenb;j++)
  {
   d[i+j]=d[i+j]+a[i]*b[j];
   d[i+j+1]+=d[i+j]/10;
   d[i+j]=d[i+j]%10;
  }
  //根据高位是否为判断整型数组的位数
  k=lena+lenb;
  while(!d[k-1])
   k--;
  //积转化为字符型
  for(i=0;i<k;i++)
   c[i]=d[k-1-i]+'0';
  if(Judge(c))//若积全为,则只输出一个
   strcpy(c,"0");
}

//整型常量的阶乘
void BigNumFact(int x)
{
 int i,k,m=0,a[1000]={0};
 a[0]=1;

 for(;x;x--)
 {//m为在求阶乘过程中a的元素个数
  for(k=i=0;i<=m;i++)
  {
   k=k+a[i]*x;//数组各个元素均乘以x(x递减),以完成阶乘的运算
   a[i]=k%10;
   k/=10;
  }
  while(k)
  {
   a[++m]=k%10;
   k/=10;
  }
 }
 //阶乘的结果转化为字符型
 for(i=0;i<=m;i++)
  c[i]=a[m-i]+'0';
 if(Judge(c))//若结果全为,则只输出一个
  strcpy(c,"0");
}
//1-整型常量的阶乘和
void BigNumFactAdd(int t)
{
 int i;
 char sum[2000],d[2000];
 //对字符串进行初始化
 memset(d,0,sizeof(d));
 memset(sum,0,sizeof(sum));
 //分别求出相应i的阶乘然后相加
 for(i=t;i>0;i--)
 {
  BigNumFact(i);
  strcpy(d,c);
  memset(c,0,sizeof(c));
  BigNumberAdd(d,sum);
  strcpy(sum,c);
  memset(c,0,sizeof(c));
 }
 strcpy(c,sum);//将结果赋值给全局变量,进行输出
}

//高精度的乘方,幂数为整型常量
void BigNumInvol(char a1[],int b1)
{
 int i;
 char temp[1000];

 strcpy(temp,a1);//注意乘方是自己乘自己,而不是结果乘结果

 for(i=2;i<b1;i++)
 {
  BigNumMultiBig(a1,temp);
  strcpy(temp,c);
  memset(c,0,sizeof(c));//将c清空,防止出现错误
 }
 //进行最后一次乘法
 BigNumMultiBig(a1,temp);
 if(Judge(c))//若结果全为,则只输出一个
  strcpy(c,"0");
}

//高精度除法--高精度除以低精度,只产生余数
int BigNumDividSmall(char a1[],int b1)
{
 if(!b1)
  return 0;
 int i,j,k,flag=0,a[1000]={0};
 char b[2000];
 memset(b,0,sizeof(b));
 k=strlen(a1);

 for(i=0;i<k;i++)
  a[i]=a1[i]-'0';
 z=0;
 for(i=0;i<k;i++)
 {
  z=a[i]+z*10;//除法过程
  b[i]=z/b1+'0';
  z=z%b1;
 }
 i=j=0;
 while(b[i++]=='0');
 for(i=i-1;i<k;i++)
  c[j++]=b[i];
 return 1;
}

//高精度除法--高精度除以高精度,只产生余数
void BigNumDividBig(char a1[],char b1[])
{
 char a[1000],b[1000],time[1000];
 int lena1,lentime,i,j,k,flag=0;

 memset(arr,0,sizeof(arr));
 //若被除数小于除数,则商为0,余数为被除数
 if(Compare(a1,b1)<0)
  strcpy(arr,a1);
 //若两数相等,则商为,余数为0
 else if(!Compare(a1,b1))
  c[0]='1';
 //若被除数大于除数
 else
 {
  j=lentime=0;
  lena1=strlen(a1);
  memset(b,0,sizeof(b));
  memset(time,0,sizeof(time));

  for(i=0;i<lena1;i++)
  {//计算得到被除数的前几位,得到整型数组形式的商
   //time的一个元素表示一次相除的商
   b[j++]=a1[i];
   flag=0;
   while(Compare(b,b1)>=0)
   {
    BigNumberSub(b,b1);
    strcpy(b,c);
    memset(c,0,sizeof(c));
    time[lentime]++;
    flag=1;//控制time的元素的位置
   }
   if(flag)//将商转换为字符
    time[lentime]+='0';
   else//当被除数前几位小于除数,商补0
    time[lentime]='0';
   if(!strcmp(b,"0"))//若b为''
    j=0;
   else//继续在b的后面加值
    j=strlen(b);
   lentime++;
  }
  k=0;
  for(i=0;i<lentime;i++)
   if(time[i]!='0')
    break;//找到time数组中第一个不为0的位置
  for(j=i;j<lentime;j++)
   c[k++]=time[j];
  strcpy(arr,b);
 }
 if(Judge(c))
  strcpy(c,"0");
 if(Judge(arr))
  strcpy(arr,"0");
}

int main()
{
 int flag=0,a3,k,i;
 char a2[1000],b2[1000];

 printf("说明:该程序适用于正整数的高精度运算,并且运算结果的位数在位以内。\n");
 while(1)
 {
  printf("/************************/\n");
  printf("1、两数相加\n");
  printf("2、两数相减\n");
  printf("3、大数与低精度相乘\n");
  printf("4、大数与大数相乘\n");
  printf("5、大数的阶乘\n");
  printf("6、大数的阶乘和\n");
  printf("7、大数的乘方\n");
  printf("8、大数除以低精度\n");
  printf("9、大数除以大数\n");
  printf("10、退出\n");
  printf("/************************/\n");

  printf("请输入你想要进行的操作数:");
  scanf("%d",&k);
  getchar();
  memset(c,0,sizeof(c));

  switch(k)
  {
  case 1:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%s",a2,b2);
   BigNumberAdd(a2,b2);
   printf("%s+%s=%s\n\n",a2,b2,c);
   break;
  case 2:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%s",a2,b2);
   BigNumberSub(a2,b2);
   printf("%s-%s=%s\n\n",a2,b2,c);
   break;
  case 3:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%d",a2,&a3);
   BigNumMultiSmall(a2,a3);
   printf("%s*%d=%s\n\n",a2,a3,c);
   break;
  case 4:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%s",a2,b2);
   BigNumMultiBig(a2,b2);
   printf("%s*%s=%s\n\n",a2,b2,c);
   break;
  case 5:
   printf("请输入您想要的阶乘数:");
   scanf("%d",&a3);
   BigNumFact(a3);
   printf("%d!=%s\n\n",a3,c);
   break;
  case 6:
   printf("请输入您想要的阶乘数:");
   scanf("%d",&a3);
   if(!a3)
   {
    printf("0!=1\n\n");
    continue;
   }
   BigNumFactAdd(a3);
   for(i=1;i<=a3;i++)
   {
    printf("%d!",i);
    if(i!=a3)
     printf("+");
   }
   printf("=%s\n\n",c);
   break;
  case 7:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%d",a2,&a3);
   BigNumInvol(a2,a3);
   printf("%s^%d=%s\n\n",a2,a3,c);
   break;
  case 8:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%d",a2,&a3);
   if(BigNumDividSmall(a2,a3))
   {
    if(!z)
     printf("%s/%d=%s\n\n",a2,a3,c);
    else
     printf("%s/%d=%s……%ld\n\n",a2,a3,c,z);
   }
   else
    printf("0不能作除数。\n\n");
   break;
  case 9:
   printf("请输入您想要进行运算的两个数字:\n");
   scanf("%s%s",a2,b2);
   if(Judge(b2))
    printf("0不能作除数。\n\n");
   else
   {
    BigNumDividBig(a2,b2);
    if(!Judge(arr))
     printf("%s/%s=%s……%s\n\n",a2,b2,c,arr);
    else
     printf("%s/%s=%s\n\n",a2,b2,c);
   }
   break;
  case 10:
   flag=1;
   printf("感谢您的使用,再见。\n\n");
   break;
  default:
   printf("对不起,您的输入有误,请重新输入。\n\n");
  }
  if(flag)
   break;
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值