zoukankan      html  css  js  c++  java
  • 高精度运算

    #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);
    
         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';
    
         k=lena>lenb?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
    
         for(j=0;j<k;j++) //将整型数组逆着转变并赋值给c字符型数组
    
             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;
    
        emset(arr,0,sizeof(arr));
    
         //若被除数小于除数,则商为,余数为被除数
    
         if(Compare(a1,b1)<0)  strcpy(arr,a1);
    
         //若两数相等,则商为,余数为
    
         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//当被除数前几位小于除数,商补
    
                       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数组中第一个不为的位置
    
             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;}


    转自:http://www.cnblogs.com/baohang/archive/2011/11/20/2255896.html

  • 相关阅读:
    EditPlus使用技巧
    PL/SQL Dev的问题
    解决httpModules 未能从程序集 XX 加载类型 XXX 的错误
    IE浏览器无法显示背景,字体显示很大问题的解决办法[转]
    如何在Outlook2003中加入农历节气
    再谈Oracle在Windows下的权限问题
    Vista下安装布署注册的问题解决
    [转]关于管理的经典故事(员工激励)
    开始应用AJAX
    Aptana IDE 中文乱码的问题解决
  • 原文地址:https://www.cnblogs.com/qiufeihai/p/2477980.html
Copyright © 2011-2022 走看看