基础高精度

小学奥数由于太简单 先咕了

写一下高精度吧...
先说一下高精度是来干嘛的,也可以直接跳过
由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
  定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
  计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
  最后将C输出即可。

先贴上两种代码

第一种 easy版本
[洛谷P1601](https://www.luogu.org/problemnew/show/P1601)
//看完后可以自己尝试打一下 在代码下面有注释

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{
    char a1[1000],b1[1000];
    int a[1000],b[1000],c[1000],lena,lenb,lenc,i,x;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
     scanf("%s",a1);scanf("%s",b1);//scanf就爆0!
    lena=strlen(a1);
    lenb=strlen(b1);
    for(i=0;i<=lena-1;i++)
     a[lena-i]=a1[i]-48;
     for(i=0;i<=lenb-1;i++)
      b[lenb-i]=b1[i]-48;
      lenc=1;
      x=0;
      while(lenc<=lena||lenc<=lenb)
      {
          c[lenc]=a[lenc]+b[lenc]+x;
          x=c[lenc]/10;
          c[lenc]%=10;
          lenc++;
      }
      c[lenc]=x;
      if(c[lenc]==0)
      lenc--;
      for(i=lenc;i>=1;i--)
        cout<<c[i];
        cout<<endl;
        return 0;
    
}

这个应该很好理解,以后贴上注释...注释来了
首先我们应该明白字符输入的顺序。
举个栗子 用数组a输入“1234” 这里的a[0]=1,a[1]=2,a[2]=3,a[3]=4,用b数组输入“5678”这里的b[0]=5,b[1]=6,b[2]=7,b[3]=8; 了解完这个,我们再回顾一下小学的竖式计算//学识浅薄不知道该咋捣鼓
1 2 3

  • 6 9

=1 9 2

由上文可知,用数组a储存数的话就成了 a[0]=1,a[1]=2,a[3]=3; b[0]=6,b[1]=9,如果他们直接相加会出现旁边竖式那样的式子吗,请认真思考一下,我就不再模拟了。(思考很重要)
这个式子显而易见,它进位了,3+9=12,他会进位,我们应该怎么办呢
(请再思考一下)

好了接下来我们逐步讲解用法
一.
1.数组其实也可以不清0..但如果测多组数据,清0就ok
2.这几个数组尽量在200以上,要不然你来算啥(这好像是废话)
3.那我们就愉快的输入两个字符数组a,b喽,并且将他们也转移成长度(这步是干什么的呢)
4.将所需输入的数据以字符数组的形式输入,建立字符数组,建立相应的整数数组,然后一一映射,以此来实现数据的输入,需要注意的是,当实现字符向数字映射时,应该减去相应的ASCII偏移值,即48。(这段是抄的,懒得打字了,以后科普一个算ASCII表小知识)
5.a[lena-i]=a1[i]-48;这步是干什么的呢?如果你认真读了上面的话并且思考了,你就知道是为什么了
6.x表示进位 现在为0.
7.如果还有不懂得和我说我再补充

int main()
{
    char a1[1000],b1[1000];
    int a[1000],b[1000],c[1000],lena,lenb,lenc,i,x;
    memset(a,0,sizeof(a));//
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
     scanf("%s",a1);scanf("%s",b1);//scanf就爆0!
    lena=strlen(a1);
    lenb=strlen(b1);
    for(i=0;i<=lena-1;i++)//‘0’就是48
     a[lena-i]=a1[i]-48;
     for(i=0;i<=lenb-1;i++)
      b[lenb-i]=b1[i]-48;
      lenc=1;
      x=0;

二.
1....咕咕咕
2.好好想一想

  while(lenc<=lena||lenc<=lenb)
      {
          c[lenc]=a[lenc]+b[lenc]+x;//两数相加 
          x=c[lenc]/10;//要进的位 
          c[lenc]%=10;//进位后的数 
          lenc++;//数据下标加一 
      }
      c[lenc]=x;
      if(c[lenc]==0)
      lenc--;//处理最高位,因为是逆序,可能会出现00
      三.1.反向输出数据。因为我们的加法是将数组反置,然后由左到右想加的,加完后,个数位在左边,所以,需要反向输出(chaode)


cout<<c[i];
        cout<<endl;
        return 0;
     
      ```

        
        高精加告一段落,高精减同理,自己试一试
        高精乘 高精除 有空有补充 但%99会咕咕咕...
下面介绍另一种  重载运算符高精度+-
```cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int M=100000000,
          P=8;     //压位
 
struct bignum
{
    int n[5000],l;     //n数组存放每个结构体中的"大数",l记录长度。
    bignum(){l=1,memset(n,0,sizeof(n));}
//-----------------------------------------------
    void init()     //输入过程
    {
        string s;
        cin>>s;
        int now=0,ct=0,c1=1; //now记录当前是n数组的第几位,ct记录已经读入多少字符了,满八进一,c1是辅助变量,因为我们是倒着读入,所以每次要乘10
        for(int i=s.length()-1;i>=0;i--)  //从s的长度-1开始
        {
            n[now]+=(s[i]-'0')*c1;
            c1*=10;
            ct++;
            if(ct==P&&i!=0)  // 如果i=0了就没有必要now++;
            {
                now++;
                ct=0;
                c1=1;
            }        
        }
        l=now+1;   //l的长度为now+1;
    }
    void print()
    {
        printf("%d",n[l-1]);
        for(int i=l-2;i>=0;i--)    
        printf("%0*d",P,n[i]);  //补零输出
        printf("\n");
    }
//-----------------------------------------------
    bignum operator + (bignum x) const     //重载加号
    {
        bignum t=*this;
        if(x.l>t.l)t.l=x.l;
        for(int i=0;i<t.l;i++)
        {
            t.n[i]+=x.n[i];
            if(t.n[i]>=M)
            {
                t.n[i+1]+=t.n[i]/M;
                t.n[i]%=M;
            }
        }
        return t;            //  注意:将t的值返回
    }
//------------------------------------------------
    bool operator < (bignum x) const      //重载小于号
    {
        bignum t=*this;
        if(t.l!=x.l)return t.l<x.l;
        for(int i=t.l-1;i>=0;i--)
        {
            if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i];
        }
        return 0;
    }
    bignum operator -(bignum x) const    //重载减号
    {
        bignum t=*this;
        if(t<x){printf("-");swap(t,x);}
        int jie =0;
        for(int i=0;i<t.l;i++)
        {
            t.n[i]-=x.n[i];
            while(t.n[i]<0)
            {
                t.n[i]+=M;
                jie++;        
            }
            t.n[i+1]-=jie;
            jie=0;
        }
        while(!t.n[t.l-1] && t.l>1)t.l--;  // 相减后有可能出现前面有0的情况,所以t.l--;
        return t;
    }
//----------------------------------------------
}a,b,c;
 
int main()
{
    a.init();        //读入字符串a和b
    b.init();
    
    c=a+b;                
    c.print();
 
    c=a-b;
    c.print();
    
    c=a*b;
    c.print();
        
    return 0;
}

注释咕咕咕

posted @ 2019-05-05 21:24  lxlql  阅读(202)  评论(0编辑  收藏  举报