我的高精度模板

该模板来源于我搜集的资料(找不到来源了。。。)

我觉得挺好用的。

每天一遍,就能背下来

我的高精度模板
#include<bits/stdc++.h>
using namespace std;
const int MAX=100;
struct hp
{
    int num[MAX];
    
    hp & operator = (const char*);
    hp & operator = (int);
    hp();
    hp(int);

    // 以下运算符可以根据实际需要来选择。
    bool operator > (const hp &) const;
    bool operator < (const hp &) const;
    bool operator <= (const hp &) const;
    bool operator >= (const hp &) const;
    bool operator != (const hp &) const;
    bool operator == (const hp &) const;

    hp operator + (const hp &) const;
    hp operator - (const hp &) const;
    hp operator * (const hp &) const;
    hp operator / (const hp &) const;
    hp operator % (const hp &) const;
    
    hp & operator += (const hp &);
    hp & operator -= (const hp &);
    hp & operator *= (const hp &);
    hp & operator /= (const hp &);
    hp & operator %= (const hp &);
};
//实现运算符的代码最好写到结构体的外面。
//"<<"和">>"由于不是hp的成员,所以必须写到结构体的外面。

//(2) 赋值和初始化
// num[0]用来保存数字位数。另外,利用10000进制可以节省空间和时间。
hp & hp::operator = (const char* c)
{
    memset(num,0,sizeof(num));
    int n=strlen(c),j=1,k=1;
    for (int i=1;i<=n;i++)
    {
        if (k==10000) j++,k=1;                // 10000进制,4个数字才算1位。
        num[j]+=k*(c[n-i]-'0');
        k*=10;
    }
    num[0]=j;
    return *this;
}

hp & hp::operator = (int a)
{
    char s[MAX];
    sprintf(s,"%d",a);
    return *this=s;
}

hp::hp() {memset(num,0,sizeof(num)); num[0]=1;}    // 目的:声明hp时无需显式初始化。
hp::hp (int n) {*this = n;}                             // 目的:支持"hp a=1;"之类的代码。

//(3) 比较运算符
//小学时候学过怎么比较两个数的大小吧?现在,虽为高中生,小学知识却从未过时……
// 如果位数不等,大小是可以明显看出来的。如果位数相等,就需要逐位比较。
bool hp::operator > (const hp &b) const
{
    if (num[0]!=b.num[0]) return num[0]>b.num[0];
    for (int i=num[0];i>=1;i--)
        if (num[i]!=b.num[i])
            return (num[i]>b.num[i]);
    return false;
}
bool hp::operator < (const hp &b) const {return b>*this;}
bool hp::operator <= (const hp &b) const {return !(*this>b);}
bool hp::operator >= (const hp &b) const {return !(b>*this);}
bool hp::operator != (const hp &b) const {return (b>*this)||(*this>b);}
bool hp::operator == (const hp &b) const {return !(b>*this)&&!(*this>b);}

//(4) 四则运算
//如果没学过竖式,或者忘了怎么用竖式算数,那么你就悲剧了……
//1.    加法和减法
// 注意:最高位的位置和位数要匹配。
hp hp::operator + (const hp &b) const
{
    hp c;
    c.num[0] = max(num[0], b.num[0]);
    for (int i=1;i<=c.num[0];i++)
    {
        c.num[i]+=num[i]+b.num[i];
        if (c.num[i]>=10000)                            // 进位
        {
            c.num[i]-=10000;
            c.num[i+1]++;
        }
    }
    if (c.num[c.num[0]+1]>0) c.num[0]++;                // 9999+1,计算完成后多了一位
    
    return c;
}

hp hp::operator - (const hp &b) const
{
    hp c;
    c.num[0] = num[0];
    for (int i=1;i<=c.num[0];i++)
    {
        c.num[i]+=num[i]-b.num[i];
        if (c.num[i]<0)                                    // 退位
        {
            c.num[i]+=10000;
            c.num[i+1]--;
        }
    }
    while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;    // 100000000-99999999
    
    return c;
}

hp & hp::operator += (const hp &b) {return *this=*this+b;}
hp & hp::operator -= (const hp &b) {return *this=*this-b;}

//2.    乘法
hp hp::operator * (const hp &b) const
{
    hp c;
    c.num[0] = num[0]+b.num[0]+1;
    for (int i=1;i<=num[0];i++)
    {
        for (int j=1;j<=b.num[0];j++)
        {
            c.num[i+j-1]+=num[i]*b.num[j];            // 和小学竖式的算法一模一样
            c.num[i+j]+=c.num[i+j-1]/10000;            // 进位
            c.num[i+j-1]%=10000;
        }
    }
    while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;    // 99999999*0
    
    return c;
}

hp & hp::operator *= (const hp &b) {return *this=*this*b;}

//3.    除法
//高精度除法的使用频率不太高。
//以下代码的缺陷是:如果b太大,运算速度会非常慢。该问题可以用二分查找解决。
hp hp::operator / (const hp &b) const
{
    hp c, d;
    c.num[0] = num[0]+b.num[0]+1;
    d.num[0] = 0;
    for (int i=num[0];i>=1;i--)
    {
        // 以下三行的含义是:d=d*10000+num[i];
        memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2);
        d.num[0]++;
        d.num[1]=num[i];

        // 以下循环的含义是:c.num[i]=d/b; d%=b;
        while (d >= b)
        {
            d-=b;
            c.num[i]++;
        }
    }
    while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;    // 99999999/99999999

    return c;//求余数 则返回d 
}
hp hp::operator % (const hp &b) const
{
hp c, d;
    c.num[0] = num[0]+b.num[0]+1;
    d.num[0] = 0;
    for (int i=num[0];i>=1;i--)
    {
        // 以下三行的含义是:d=d*10000+num[i];
        memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2);
        d.num[0]++;
        d.num[1]=num[i];

        // 以下循环的含义是:c.num[i]=d/b; d%=b;
        while (d >= b)
        {
            d-=b;
            c.num[i]++;
        }
    }
    while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;    // 99999999/99999999
    return d;
}

hp & hp::operator /= (const hp &b) {return *this=*this/b;}
hp & hp::operator %= (const hp &b) {return *this=*this%b;}

//4. 二分优化的除法
//高精度除法速度慢,就慢在上面的while (d>=b)处。如果我们用二分法去猜d/b的值,速度就快了。
/*hp hp::operator / (const hp & b) const
{
    hp c, d;
    c.num[0] = num[0]+b.num[0]+1;
    d.num[0] = 0;
    for (int i=num[0];i>=1;i--)
    {
        // 以下三行的含义是:d=d*10000+num[i];
        memmove(d.num+2, d.num+1, sizeof(d.num)-sizeof(int)*2);
        d.num[0]++;
        d.num[1]=num[i];

        // 以下循环的含义是:c.num[i]=d/b; d%=b; 利用二分查找求c.num[i]的上界。
        // 注意,这里是二分优化后除法和朴素除法的区别!
        int left=0, right=9999, mid;
        while (left < right)
        {
            mid = (left+right)/2;
            if (b*hp(mid) <= d) left=mid+1;
            else right=mid;
        }
        c.num[i]=right-1;
        d=d-b*hp(right-1);
    }
    while (c.num[c.num[0]]==0&&c.num[0]>1) c.num[0]--;    // 99999999/99999999

    return c;            // 求余数就改成return d;
}*/

//(5) 输入/输出
//有了这两段代码,就可以直接用cout和cin输出、输入高精度数了。
ostream & operator << (ostream & o, hp &n)
{
    o<<n.num[n.num[0]];
    for (int i=n.num[0]-1;i>=1;i--)
    {
        o.width(4);
        o.fill('0');
        o<<n.num[i];
    }
    return o;
}

istream & operator >> (istream & in, hp &n)
{
    char s[MAX];
    in>>s;
    n=s;
    return in;
}
int main()
{
    
}
My 模板

 

上一篇:玩转大厂常用的大数据安全组件Ranger


下一篇:递归,面向对象初识