高精度算法(c++版)

title: 高精度算法(c++版)
date: 2019-05-23 09:56:21
tags: 高精度

高精度算法
高精度加法

每次记得加 进位t 就行

#include <iostream>
#include <cstring>
#include <vector>
const int maxn=1e7+5;
using namespace std;
vector<int> aa,bb;

//c=a+b
vector<int> add(vector<int> &aa,vector<int> &bb)//这里加上&是为了防止把aa copy一遍,不拷贝整个数组就会快很多
{
    vector<int> cc;
    int t=0;//进位 初始时最低位进位为0
    for(int i=0;i<aa.size()||i<bb.size();i++)//任一个字串长度,其实取一个max就可以了
    {
        if(i<aa.size())
        t+=aa[i];
        if(i<bb.size())
        t+=bb[i];//此时 一位上的 t=a+b+t
        cc.push_back(t%10);//对应和的这一位的数有了
        t/=10;//向更高一位的进位
    }
    
    if(t)//最高位如果还有进位,记得在末尾再加一位
    cc.push_back(t);
    
    return cc;
}

int main()
{
    string a,b;
    cin>>a>>b;//12345
    for(int i=a.size()-1;i>=0;i--)
    aa.push_back(a[i]-'0'); //54321
    for(int i=b.size()-1;i>=0;i--)//因为考虑到最高位进位的问题,所以让个位在最前面比较好,这样只需要在最后一位加上进位数字即可
    bb.push_back(b[i]-'0');
    
    auto cc=add(aa,bb);
    
    for(int i=cc.size()-1;i>=0;i--)//注意要倒着输出
    printf("%d",cc[i]);
    cout<<endl;
    return 0;
}
高精度减法

每次要保证

A-B时

如果A>=B --> A-B

如果A<B --> - (B-A)

注意一下前导0的处理

#include <iostream>
#include <cstring>
#include <vector>
const int maxn=1e7+5;
using namespace std;
vector<int> aa,bb;
//判断是否有aa>=bb
bool cmp(vector<int> &aa,vector<int> &bb)
{
    if(aa.size()!=bb.size())
    return aa.size()>bb.size();
    
    for(int i=aa.size()-1;i>=0;i--)
    {
        if(aa[i]!=bb[i])
        return aa[i]>bb[i];
    }
    return true;//相等
}

//cc=aa-bb
vector<int> sub(vector<int> &aa,vector<int> &bb)
{
    vector<int> cc;
    int t=0;
    for(int i=0;i<aa.size();i++)//这里我们保证aa大于bb,从个位开始处理
    {
        t=aa[i]-t;//t=aa[i]-bb[i]-t; 但是我们要看bb[i]有没有这一位
        if(i<bb.size())
        t-=bb[i];
        
        cc.push_back((t+10)%10);//因为t可能是个负数,不够减的时候向高位借1 +10
        //这种写法可以涵盖t是正或负数两种情况
        
        if(t<0)
        t=1;//向高一位借了1 要减掉
        else
        t=0;
        
    }
    //这里还要特别注意去掉前导0 比如 123-120=003
    while(cc.size()>1&&cc.back()==0)//还要注意 如果结果为0,最后要留一个0
    //cc.back() 表示cc的最后一个是0
    {
        cc.pop_back();
    }
    return cc;
}

int main()
{
    string a,b;//注意这里如果有负数在运算中  我们可以设定标记判断  总之一定可以变成绝对值相加或者绝对值相减的 
               //特殊处理一下输入输出即可
    cin>>a>>b;//12345
    for(int i=a.size()-1;i>=0;i--)
    aa.push_back(a[i]-'0'); //54321
    for(int i=b.size()-1;i>=0;i--)//因为考虑到最高位进位的问题,所以让个位在最前面比较好,这样只需要在最后一位加上进位数字即可
    bb.push_back(b[i]-'0');
    
    vector<int> cc;
    //注意这里要判断一下aa,bb谁大
    if(cmp(aa,bb))
    cc=sub(aa,bb);
    else
    {
        cc=sub(bb,aa);
        printf("-");
    }
    
    for(int i=cc.size()-1;i>=0;i--)//注意要倒着输出
    printf("%d",cc[i]);
    cout<<endl;
    return 0;
}
高精度乘法

取每一位去*b,然后做带进位t的加法

#include <iostream>
#include <vector>
using namespace std;
vector<int>aa;
vector<int> mul(vector<int> &aa,int bb)
{
    vector<int> cc;
    int t=0;
    /*或者 简单点 这样
    for(int i=0;i<aa.size()||t;i++)
    {
        if(i<aa.size())
        t+=aa[i]*bb;
        
        cc.push_back(t%10);
        t/=10;
    }
    */
    for(int i=0;i<aa.size();i++)
    {
        t+=aa[i]*bb;
        cc.push_back(t%10);
        t/=10;
    }
    
    while(t)  //也可以直接在上面加||t
    {
        cc.push_back(t%10);//还要注意这个tt可能不止一位数  不过 为什么这个cc的一位不能放两位数以上??会爆内存?
        t/=10;
    }
    return cc;
}
int main()
{
    string a;
    int bb;
    cin>>a>>bb;
    for(int i=a.size()-1;i>=0;i--)
    aa.push_back(a[i]-'0');
    
    auto cc=mul(aa,bb);
    
    for(int i=cc.size()-1;i>=0;i--)
    printf("%d",cc[i]);
    cout<<endl;
    
    return 0;
}
高精度除法
#include <iostream>
#include <algorithm>
#include <vector>
const int maxn=1e6+5;
using namespace std;
vector<int> aa;
//cc=aa/bb
vector<int> div(vector<int> &aa,int bb,int &r)
{
    vector<int> cc;
    r=0;
    //注意 除法是从最高位开始算
    for(int i=aa.size()-1;i>=0;i--)
    {
        r=r*10+aa[i];
        cc.push_back(r/bb);
        r%=bb;
    }
    reverse(cc.begin(),cc.end());//因为 在main函数中是倒着输出的,所以这里要reverse一下,本来可以就直接顺着输出cc的
    //这里还要特别注意去掉前导0
    while(cc.size()>1&&cc.back()==0)
        cc.pop_back();
        
    return cc;
}
int main()
{
    string a;
    int bb;
    cin>>a>>bb;
    for(int i=a.size()-1;i>=0;i--)
    aa.push_back(a[i]-'0');
    
    int r;
    auto cc=div(aa,bb,r);
    
    for(int i=cc.size()-1;i>=0;i--)
    printf("%d",cc[i]);
    cout<<endl<<r<<endl;
}

压位 可以加速

加法可以压9位,乘法一般压4位 (因为如果5位 (10^5^)^2^会爆int)

#include <iostream>
#include <cstring>
#include <vector>
const int maxn=1e7+5;
using namespace std;
vector<int> aa,bb;
const int base=1e9;
//c=a+b
vector<int> add(vector<int> &aa,vector<int> &bb)//这里加上&是为了防止把aa copy一遍,不拷贝整个数组就会快很多
{
    vector<int> cc;
    int t=0;//进位 初始时最低位进位为0
    for(int i=0;i<aa.size()||i<bb.size();i++)//任一个字串长度,其实取一个max就可以了
    {
        if(i<aa.size())
        t+=aa[i];
        if(i<bb.size())
        t+=bb[i];//此时 一位上的 t=a+b+t
        cc.push_back(t%base);//对应和的这一位的数有了
        t/=base;//向更高一位的进位
    }
    
    if(t)//最高位如果还有进位,记得在末尾再加一位
    cc.push_back(t);
    
    return cc;
}//主要改的是/base

int main()
{
    string a,b;
    cin>>a>>b;//12345
    for(int i=a.size()-1,s=0,cnt=0,t=1;i>=0;i--)//数据处理要注意
    {
        //s=s*10+a[i]-'0';//因为是倒着输入的,所以要注意这里
        s+=(a[i]-'0')*t;
        cnt++;
        t*=10;
        if(cnt==9||i==0)
        {
            aa.push_back(s);
            s=cnt=0;//里面要注意重新初始化
            t=1;
        }
    }
    //aa.push_back(a[i]-'0'); //54321
    for(int i=b.size()-1,s=0,cnt=0,t=1;i>=0;i--)//因为考虑到最高位进位的问题,所以让个位在最前面比较好,这样只需要在最后一位加上进位数字即可
    {
        //s=s*10+a[i]-'0';
        s+=(b[i]-'0')*t;
        cnt++;
        t*=10;
        if(cnt==9||i==0)
        {
            bb.push_back(s);
            s=cnt=0;
            t=1;
        }  
    }
    //bb.push_back(b[i]-'0');
    
    auto cc=add(aa,bb);
    
    cout<<cc.back();
    for(int i=cc.size()-2;i>=0;i--)//注意要倒着输出
    printf("%09d",cc[i]);//高位不足9位要补0
    cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值