zoukankan      html  css  js  c++  java
  • 高精度模板

    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;
    struct Wint:vector<int>//用标准库vector做基类,完美解决位数问题,同时更易于实现
    {
        //将低精度转高精度的初始化,可以自动被编译器调用
        //因此无需单独写高精度数和低精度数的运算函数,十分方便
        Wint(int n=0)//默认初始化为0,但0的保存形式为空
        {
            push_back(n);
            check();
        }
        Wint& check()//在各类运算中经常用到的进位小函数,不妨内置
        {
            while(!empty()&&!back())pop_back();//去除最高位可能存在的0
            if(empty())return *this;
            for(int i=1; i<size(); ++i)
            {
                (*this)[i]+=(*this)[i-1]/10;
                (*this)[i-1]%=10;
            }
            while(back()>=10)
            {
                push_back(back()/10);
                (*this)[size()-2]%=10;
            }
            return *this;//为使用方便,将进位后的自身返回引用
        }
    };
    //输入输出
    istream& operator>>(istream &is,Wint &n)
    {
        string s;
        is>>s;
        n.clear();
        for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
        return is;
    }
    ostream& operator<<(ostream &os,const Wint &n)
    {
        if(n.empty())os<<0;
        for(int i=n.size()-1; i>=0; --i)os<<n[i];
        return os;
    }
    //比较,只需要写两个,其他的直接代入即可
    //常量引用当参数,避免拷贝更高效
    bool operator!=(const Wint &a,const Wint &b)
    {
        if(a.size()!=b.size())return 1;
        for(int i=a.size()-1; i>=0; --i)
            if(a[i]!=b[i])return 1;
        return 0;
    }
    bool operator==(const Wint &a,const Wint &b)
    {
        return !(a!=b);
    }
    bool operator<(const Wint &a,const Wint &b)
    {
        if(a.size()!=b.size())return a.size()<b.size();
        for(int i=a.size()-1; i>=0; --i)
            if(a[i]!=b[i])return a[i]<b[i];
        return 0;
    }
    bool operator>(const Wint &a,const Wint &b)
    {
        return b<a;
    }
    bool operator<=(const Wint &a,const Wint &b)
    {
        return !(a>b);
    }
    bool operator>=(const Wint &a,const Wint &b)
    {
        return !(a<b);
    }
    //加法,先实现+=,这样更简洁高效
    Wint& operator+=(Wint &a,const Wint &b)
    {
        if(a.size()<b.size())a.resize(b.size());
        for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
        return a.check();
    }
    Wint operator+(Wint a,const Wint &b)
    {
        return a+=b;
    }
    //减法,返回差的绝对值,由于后面有交换,故参数不用引用
    Wint& operator-=(Wint &a,Wint b)
    {
        if(a<b)swap(a,b);
        for(int i=0; i!=b.size(); a[i]-=b[i],++i)
            if(a[i]<b[i])//需要借位
            {
                int j=i+1;
                while(!a[j])++j;
                while(j>i)
                {
                    --a[j];
                    a[--j]+=10;
                }
            }
        return a.check();
    }
    Wint operator-(Wint a,const Wint &b)
    {
        return a-=b;
    }
    //乘法不能先实现*=,原因自己想
    Wint operator*(const Wint &a,const Wint &b)
    {
        Wint n;
        n.assign(a.size()+b.size()-1,0);
        for(int i=0; i!=a.size(); ++i)
            for(int j=0; j!=b.size(); ++j)
                n[i+j]+=a[i]*b[j];
        return n.check();
    }
    Wint& operator*=(Wint &a,const Wint &b)
    {
        return a=a*b;
    }
    //除法和取模先实现一个带余除法函数
    Wint divmod(Wint &a,const Wint &b)
    {
        Wint ans;
        for(int t=a.size()-b.size(); a>=b; --t)
        {
            Wint d;
            d.assign(t+1,0);
            d.back()=1;
            Wint c=b*d;
            while(a>=c)
            {
                a-=c;
                ans+=d;
            }
        }
        return ans;
    }
    Wint operator/(Wint a,const Wint &b)
    {
        return divmod(a,b);
    }
    Wint& operator/=(Wint &a,const Wint &b)
    {
        return a=a/b;
    }
    Wint& operator%=(Wint &a,const Wint &b)
    {
        divmod(a,b);
        return a;
    }
    Wint operator%(Wint a,const Wint &b)
    {
        return a%=b;
    }
    //顺手实现一个快速幂,可以看到和普通快速幂几乎无异
    Wint pow(const Wint &n,const Wint &k)
    {
        if(k.empty())return 1;
        if(k==2)return n*n;
        if(k.back()%2)return n*pow(n,k-1);
        return pow(pow(n,k/2),2);
    }
    //通过重载运算符,还可以实现++、--、^、!、逻辑运算符等很多运算,十分简单,此处都不写了
    int main()//现在你完全可以像int一般便捷地使用Wint,如下
    {
        Wint a,b;
        //可以把b改成int型,仍能正常使用
        cin>>a>>b;
        cout<<(a<b)<<endl
            <<(a==b)<<endl
            <<a+b<<endl
            <<a-b<<endl
            <<a*b<<endl
            <<a/b<<endl
            <<a%b<<endl
            <<pow(a,b);
    }

    这里要注意一个地方就是减法计算的是两个大数的差的绝对值。所以如果你要输出一个负数的话,要提前判两个大数的大小然后决定是否输出cout<<" - ";

  • 相关阅读:
    物理删除文件 业务层
    页面在本机可以显示,其它机器不可以看到页面
    我对asp.net并行请求数量的理解
    分布式缓存Memcached
    任意两个对象赋值,用Spring.Objects.ObjectWrapper效率比直接反射还慢?
    在Linux(RHEL5.5)里用mono2.8.2和jexus4.1运行.net3.5下的MVC2.0过程记录
    Nhibernate连接oracle数据库,主键ID用序列生成时连接数据库IO次数分析
    Sqlserver别太信任SysComments表中的text字段
    .net4.0线程池取消执行的实际应用
    spring.net、castle windsor、unity实现aop、ioc的方式和简单区别
  • 原文地址:https://www.cnblogs.com/rainyskywx/p/10994979.html
Copyright © 2011-2022 走看看