高精度计算

转载: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("\n余数=%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("\n余数=");
    for(i = kd - 1; i >= 0; i--)  printf("%d", a[i]);
    exit(1);
  }
  if(t2 == 2)
  {
    printf("商 = 1");
    printf("\n余数 = 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("\n余数 = ");
  if(kk < 0)
  {
    printf("0");
    exit(1);
  }
  for(i = kk; i >= 0; i--)  printf("%d", a[i]);
}
posted @ 2020-09-16 20:55  莫空折枝  阅读(133)  评论(0编辑  收藏  举报