高精度

Posted zzzc18

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高精度相关的知识,希望对你有一定的参考价值。

其实高精度就按你平时手算的的方法写出来就好了
这份代码用 \(long \ long\)\(8\)
高精乘可以用FFT优化(这里没有)
高精除需要使用 \(2\) 的幂次来试商,这样会快很多

其实这东西要的就是一个,一般用到高精的东西最后不是别的地方错了,而是高精错了。


#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

namespace Bignum_Class{
    const int WIDTH = 50000+9;
    const int MOD = 100000000;
    char BUF[WIDTH];
    typedef long long LL;
    struct Num{
        vector<LL> vec;
    };
    struct PAIR{
        Num first;
        bool second;
    };
    Num Input(){
        Num re;
        scanf("%s",BUF+1);
        int len=strlen(BUF+1);
        for(int i=len;i>=8;i-=8){
            LL tmp=0;
            for(int j=7;j>=0;j--){
                tmp=tmp*10+BUF[i-j]-‘0‘;
            }
            re.vec.push_back(tmp);
        }
        len=len%8;
        if(len!=0){
            LL tmp=0;
            for(int i=1;i<=len;i++){
                tmp=tmp*10+BUF[i]-‘0‘;
            }
            re.vec.push_back(tmp);
        }
        return re;
    }

    void Print(const Num &X,char s=0,bool sign=1){
        if(!sign)putchar(‘-‘);
        sprintf(BUF,"%lld",X.vec[X.vec.size()-1]);
        printf("%s",BUF);
        for(int i=X.vec.size()-2;i>=0;i--){
            sprintf(BUF,"%08lld",X.vec[i]);
            printf("%s",BUF);
        }
        if(s)
            putchar(s);
    }

    bool operator < (const Num &A,const Num &B){
        if(A.vec.size()!=B.vec.size()){
            return A.vec.size()<B.vec.size();
        }
        int len=A.vec.size()-1;
        for(int i=len;i>=0;i--){
            if(A.vec[i]==B.vec[i])continue;
            if(A.vec[i]>B.vec[i])return false;
            if(A.vec[i]<B.vec[i])return true;
        }
        return false;
    }
    bool operator <= (const Num &A,const Num &B){
        if(A.vec.size()!=B.vec.size()){
            return A.vec.size()<B.vec.size();
        }
        int len=A.vec.size()-1;
        for(int i=len;i>=0;i--){
            if(A.vec[i]==B.vec[i])continue;
            if(A.vec[i]>B.vec[i])return false;
            if(A.vec[i]<B.vec[i])return true;
        }
        return true;
    }
    bool operator > (const Num &A,const Num &B){
        if(A.vec.size()!=B.vec.size()){
            return A.vec.size()>B.vec.size();
        }
        int len=A.vec.size()-1;
        for(int i=len;i>=0;i--){
            if(A.vec[i]==B.vec[i])continue;
            if(A.vec[i]<B.vec[i])return false;
            if(A.vec[i]>B.vec[i])return true;
        }
        return false;
    }
    bool operator >= (const Num &A,const Num &B){
        if(A.vec.size()!=B.vec.size()){
            return A.vec.size()>B.vec.size();
        }
        int len=A.vec.size()-1;
        for(int i=len;i>=0;i--){
            if(A.vec[i]==B.vec[i])continue;
            if(A.vec[i]<B.vec[i])return false;
            if(A.vec[i]>B.vec[i])return true;
        }
        return true;
    }
    bool operator == (const Num &A,const Num &B){
        if(A.vec.size()!=B.vec.size()){
            return false;
        }
        int len=A.vec.size()-1;
        for(int i=len;i>=0;i--){
            if(A.vec[i]!=B.vec[i]) return false;
        }
        return true;
    }

    template<typename type>
    Num Change_Mode(type val){
        LL tmp=val;
        Num re;
        re.vec.push_back(tmp);
        return re;
    }

    Num Move_to_Length(const Num &A,int L){
        Num re;
        re.vec.resize(A.vec.size()+L);
        for(int i=0,j=L;j<re.vec.size();i++,j++){
            re.vec[j]=A.vec[i];
        }
        return re;
    }

    Num operator +(Num &A,Num &B){
        Num re;
        int maxx=max(A.vec.size(),B.vec.size());
        maxx++;
        re.vec.resize(maxx);
        for(int i=0;i<A.vec.size();i++){
            re.vec[i]=A.vec[i];
        }
        for(int i=0;i<B.vec.size();i++){
            re.vec[i]+=B.vec[i];
            re.vec[i+1]+=re.vec[i]/MOD;
            re.vec[i]%=MOD;
        }
        for(int i=0;i<re.vec.size();i++){
            re.vec[i+1]+=re.vec[i]/MOD;
            re.vec[i]%=MOD;
        }
        while(!re.vec.back() && re.vec.size()>1)
            re.vec.pop_back();
        return re;
    }

    Num subtraction(const Num &A,const Num &B){
        Num re=A;
        int minn=B.vec.size();
        for(int i=minn-1;i>=0;i--)
            re.vec[i]-=B.vec[i];
        for(int i=0;i<(re.vec.size()-1);i++){
            if(re.vec[i]<0){
                re.vec[i]+=MOD;
                re.vec[i+1]--;
            }
        }
        while(!re.vec.back() && re.vec.size()>1)
            re.vec.pop_back();
        return re;
    }

    PAIR operator - (const Num &A,const Num &B){
        Num re;
        if(A==B){
            re.vec.push_back(0);
            return (PAIR){re,1};
        }
        bool pd=1;
        if(A<B){re=subtraction(B,A);pd=0;}
        else re=subtraction(A,B);
        return (PAIR){re,pd};
    }
    
    Num operator *(const Num &A,const Num &B){
        Num re;
        int len=A.vec.size()+B.vec.size()+1;
        while(re.vec.size()<len)re.vec.push_back(0);
        for(int i=0;i<A.vec.size();i++){
            for(int j=0;j<B.vec.size();j++){
                re.vec[i+j]+=A.vec[i]*B.vec[j];
                re.vec[i+j+1]+=re.vec[i+j]/MOD;
                re.vec[i+j]%=MOD;
            }
        }
        for(int i=0;i<re.vec.size()-2;i++){
            re.vec[i+1]+=re.vec[i]/MOD;
            re.vec[i]%=MOD;
        }
        while(!re.vec.back() && re.vec.size()>1)
            re.vec.pop_back();
        return re;
    }

    Num DivMod(const Num &A,const Num &B,Num &R){
        R=A;
        Num re;
        re.vec.resize(A.vec.size()-B.vec.size()+1);
        Num tmp10,tmp2;
        for(int i=re.vec.size()-1;i>=0;i--){
            tmp10=Move_to_Length(B,i);
            for(int j=26;j>=0;j--){
                LL val=1<<j;
                tmp2=tmp10*Change_Mode(val);
                if(R>=tmp2){
                    R=(R-tmp2).first;
                    re.vec[i]+=val;
                }
            }
        }
        while(!re.vec.back() && re.vec.size()>1) re.vec.pop_back();
        return re;
    }


    Num operator / (const Num &A,const Num &B){
        Num re;
        Num jud;
        jud.vec.push_back(0);
        if(B==jud){
            re.vec.push_back(23332333);
            return re;
        }
        if(A<B){
            re.vec.push_back(0);
            return re;
        }
        Num x;
        re=DivMod(A,B,x);
        return re;
    }

    Num operator % (const Num &A,const Num &B){
        Num re;
        Num jud;
        jud.vec.push_back(0);
        if(B==jud){
            re.vec.push_back(23332333);
            return re;
        }
        if(A==B){
            re.vec.push_back(0);
            return re;
        }
        if(A<B){
            return A;
        }
        DivMod(A,B,re);
        return re;
    }
}

using namespace Bignum_Class;
Num A,B,D;
PAIR C;

int main(){
    //freopen("calc.in","r",stdin);
    //freopen("calc.out","w",stdout);
    A=Input();
    B=Input();
    Print(A+B,\n);
    C=A-B;
    Print(C.first,\n,C.second);
    Print(A*B,\n);
    Print(A/B,\n);
    Print(A%B,\n);
    return 0;
}

以上是关于高精度的主要内容,如果未能解决你的问题,请参考以下文章

1049 数列的片段和(注意精度!!)

片段和活动之间没有传递值

Joda-Time 库指定 mili 秒精度

传递双精度值返回未知值C.

为啥我需要在 webgl 着色器中定义一个精度值?

unity 优化整理