• 高精度计算


    转载:https://www.cnblogs.com/ECJTUACM-873284962/p/6509429.html
    高精度的计算包括几个方面:
    1:对数据的存取
    2:对数据的加减乘除(运算)
    下面我将用着两部分来讲解:
    1:高精度的存取.
    2高精度的运算
    1:用字符串读入然后转换成数组.

     
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N=100;//最多100位
    int main()
    {
    int a[N+1],i;
    string s1;
    cin>>s1;//数s1
    memset(a,0,sizeof(a)); //数组清0
    a[0]=s1.length(); //位数
    for(i=1;i<=a[0];i++) a[i]=s1[a[0]-i]-'0';//将字符转为数字并倒序存储.
    return 0;
    }
    

    2:直接读取(这种针对数字本身没有超界的)

     
    #include <iostream>
    using namespace std;
    const int N=100;//最多100位
    int main()
    {
    int a[N+1],i,s,key;
    cin>>key;//数key
    memset(a,0,sizeof(a)); //数组清0
    i=0;//第0位
    while(key)  //当key大于0
    {
      a[++i]=key%10;//取第i位的数
      key=key/10;
    }
    a[0]=i; //共i位数
    return 0;
    }
    

    2:高精度的运算:
    1比较:

    int compare(int a[],int b[])   //比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0
    {int i;
    if (a[0]>b[0]) return 1;//a的位数大于b则a比b大
    if (a[0]<b[0]) return -1;//a的位数小于b则a比b小
    //比较剩下的位
    for(i=a[0];i>0;i--)  //从高位到低位比较
         {if (a[i]>b[i]) return 1;
          if (a[i]<b[i]) return -1;}
    return 0;//各位都相等则两数相等。
    }
    
      2高进度加法:本质就是模拟竖式运算,如果大于9了就进位就让前一位加加
    
    int plus(int a[],int b[]) //计算a=a+b
    {
          int i,k;
          k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位数最大的一个的位数
          for(i=1;i<=k;i++)
          {
                a[i+1]+=(a[i]+b[i])/10;  //若有进位,则先进位
                a[i]=(a[i]+b[i])%10;}  //计算当前位数字,注意:这条语句与上一条不能交换。
                if(a[k+1]>0) a[0]=k+1;  //修正新的a的位数(a+b最多只能的一个进位)
                else a[0]=k;
                return 0;
          }
    }
    

    3:高精度减法:

    int gminus(int a[],int b[]);//计算a=a-b,返加符号位0:正数 1:负数
    { 
          int flag,i
          flag=compare(a,b); //调用比较函数判断大小
          if (falg==0)//相等
          {
                memset(a,0,sizeof(a));
                return 0;
          }  //若a=b,则a=0,也可在return前加一句a[0]=1,表示是 1位数0
          if(flag==1) //大于
          {  
          for(i=1;i<=a[0];i++)
          {  
                if(a[i]<b[i])
                { 
                     a[i+1]--;
                     a[i]+=10;
                } //若不够减则向上借一位
                a[i]=a[i]-b[i];
          }
          while(a[a[0]]==0) a[0]--; //修正a的位数
          return 0;
          }
         if (flag==-1)//小于  则用a=b-a,返回-1
          { 
             for(i=1;i<=b[0];i++)       
              {  
                if(b[i]<a[i])
                { 
                   b[i+1]--;
                   b[i]+=10;
                } //若不够减则向上借一位
                a[i]=b[i]-a[i];
             }
         a[0]=b[0];
         while(a[a[0]]==0) a[0]--; //修正a的位数
         return -1;
       }
    }
    

    高精度乘法:高精度乘单精度数,单精度数是指通常的整型数

    int multi1(int a[],long  key) //a=a*key,key是单精度数
    {
          int i,k;
          if (key==0)
          {
            memset(a,0,sizeof(a));
            a[0]=1;
            return 0;
          } //单独处理key=0
          for(i=1;i<=a[0];i++)a[i]=a[i]*key;//先每位乘起来
          for(i=1;i<=a[0];i++){a[i+1]+=a[i]/10;a[i]%=10;} //进位
          //注意上一语句退出时i=a[0]+1
          while(a[i]>0) {a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++];}  //继续处理超过原a[0]位数的进位,修正a的位数
          return 0;
    }
    

    高精度除法:算法:按照从高位到低位的顺序,逐位相除。在除到第j位时,该位在接受了来自第j+1位的余数后与除数相除,如果最高位为零,则商的长度减一。源程序如下(模拟竖式的运算)

    #include  <stdio.h>
    #define   N  500
    main()
    {
      int  a[N] = {0}, c[N] = {0};
      int  i, k, d, b;
      char  a1[N];
      printf("Input 除数:");
      scanf("%d", &b);
      printf("Input 被除数:");
      scanf("%s", a1);
      k = strlen(a1);
      for(i = 0; i < k; i++)  a[i] = a1[k - i - 1] - '0';
      d = 0;
      for(i = k - 1; i >= 0 ; i--)
      {
         d = d * 10 + a[i];
         c[i] = d / b;
         d = d % b;
      }
      while(c[k - 1] == 0 && k > 1)  k--;
      printf("商=");
      for(i = k - 1; i >= 0; i--)  printf("%d", c[i]);
      printf("
    余数=%d", d);
    }
    

    高精度乘以高精度:算法:用数组保存两个高精度数,然后逐位相乘,注意考虑进位和总位数。源程序如下:

    #include  <stdio.h>
    main()
    {
      int  a[240] = {0}, b[240] = {0}, c[480] = {0};
      int  i, j, ka, kb, k;
      char  a1[240], b1[240];
      gets(a1);
      ka = strlen(a1);
      gets(b1);
      kb = strlen(b1);
      k = ka + kb;
      for(i = 0; i < ka; i++)  a[i] = a1[ka-i-1] - '0';
      for(i = 0; i < kb; i++)  b[i] = b1[kb-i-1] - '0';
      for(i = 0; i < ka; i++)
        for(j = 0; j < kb; j++)
        {
          c[i + j] = c[i + j] + a[i] * b[j];
          c[i + j +1] = c[i + j +1] + c[i + j]/10;
          c[i + j] = c[i + j] % 10;
        }
      if(!c[k])  k--;
      for(i = k-1; i >= 0; i--)  printf("%d", c[i]);
    }
    

    高精度初一高精度:

    #include  <stdio.h>
    #define   N  500
    int  bj(int a[], int b[], int k1, int k2)   /*比较大小函数*/
    {
       int i, t, flag;       /*flag作标志位*/
       if(k1 < k2)
         flag = 0;           /*被除数小于除数返回0*/
       else if(k1 > k2)
              flag = 1;      /*被除数大于除数返回1*/
            else
              {              /*被除数和除数位数相等则逐位进行比较*/
                i = k1;
                t = 0;
                while(t == 0 && i > 0)
                {
                  if(a[i] > b[i]) {t = 1; flag = 1;}
                  else if(a[i] == b[i])  i--;
                  else  {t = 1; flag = 0;}
                }
                if(i == 0 && t == 0)  flag = 2;     /*被除数等于除数返回2*/
              }
      return flag;
    }
    int  jf(int a[], int b[], int k1, int k2)       /*减法运算*/
    {
      int  i, k, d[N];
      for(i = 0; i < k2; i++)  d[i] = b[i];        /*把除数赋给数组d*/
      for(i = k2; i < N; i++)  d[i] = 0;          /*d数组无数据的高位置0*/
      k = k1 - k2 - 1;                            /*计算减法起始位置*/
      if(k < 0)  k = 0;
      if(k > 0)
      {
        for(i = k2 - 1; i >= 0; i--)  d[i + k] = d[i];  /*移动减数位数与被减数对齐*/
        for(i = 0; i < k; i++)  d[i] = 0;            /*移动后的其余位置0*/
      }
      for(i = 0; i < k1; i++)
      {
        if(a[i] >= d[i])  a[i] -= d[i];
        else
        {
          a[i + 1] = a[i + 1] - 1;
          a[i] = 10 + a[i] - d[i];
        }
      }
      return k;
    }
    main()
    {
      int  a[N] = {0}, b[N] = {0}, c[N] = {0}, d[N] = {0};
      int  i, ka, kb, m, t, t1, t2, k, x, kd, kk;
      char  a1[N], b1[N];
      printf("Input 被除数:");
      scanf("%s", a1);
      ka = strlen(a1);
      for(i = 0; i < ka; i++)  a[i] = a1[ka - i -1] - '0';
      printf("Input 除数:");
      scanf("%s", b1);
      kb = strlen(b1);
      for(i = 0; i < kb; i++)  b[i] = b1[kb - i -1] - '0';
      kd = ka;    /*保存被除数位数  */
      t2 = bj(a, b, ka, kb);
      m = 0;
      do
      {
        while(a[ka - 1] == 0)  ka--;
        t = bj(a, b, ka, kb);
        if(t >= 1)
        {
          k = jf(a, b, ka, kb);
          c[k]++;
          if(k > m)  m = k;
          t1 = 0;
          for(i = k; i <= m; i++)
          {
            x = c[i] + t1;
            c[i] = x % 10;
            t1 = x / 10;
          }
          if(t1 > 0)  {m++; c[m] = t1;  }
        }
      }while(t == 1);
      if(t2 == 0)
      {
        printf("商=0");
        printf("
    余数=");
        for(i = kd - 1; i >= 0; i--)  printf("%d", a[i]);
        exit(1);
      }
      if(t2 == 2)
      {
        printf("商 = 1");
        printf("
    余数 = 0");
        exit(1);
      }
      kk = kd;
      while(!c[kd - 1])  kd--;
      printf("商 = ");
      for(i = kd - 1; i >= 0; i--)  printf("%d", c[i]);
      while(!a[kk])  kk--;
      printf("
    余数 = ");
      if(kk < 0)
      {
        printf("0");
        exit(1);
      }
      for(i = kk; i >= 0; i--)  printf("%d", a[i]);
    }
    
  • 相关阅读:
    HDU 5775 Bubble Sort
    HDU 5763 Another Meaning
    HDU 5773 The All-purpose Zero
    HDU 5768 Lucky7
    HDU 5769 Substring
    SPOJ 705 New Distinct Substrings
    POJ 3261 Milk Patterns
    HDU 1521 排列组合 指数型母函数
    HDU 1023 Traning Problem (2) 高精度卡特兰数
    HDU 2082 母函数模板题
  • 原文地址:https://www.cnblogs.com/resuscitate/p/13681368.html
Copyright © 2020-2023  润新知