模板:高精度

一个普普通通的压位大整数类


封装功能

  1. 通过整型、字符串赋值与初始化方式 (默认初值为0)

    Bign a(2147483648);
    
    a="234566464322469989856";
    
  2. 大整数类与大整数类大整数类与整型加、减、乘

    乘法未经过FFT优化 ( to-do++ )

    Bign a,b;ll x;
    
    a*b+x-a;//混合类型运算时运算顺序不变但请不要将整型置于算式首:((a*b)+x)-a
    
  3. 大整数类与整型除、取余

    Bign a;ll b;
    
    a/b+a%b;
    
  4. 大整数与大整数除、取余 (这里用的是倍增优化,FFT我太蒻了看不懂,可能会很慢慎用)

    Bign a,b;
    
    a/b;
    
  5. 大整数类的位移操作 (这玩意建议最多不要位移超过10位,但对于少量的位移,效率还是会更高一点)

    Bign a;
    
    a<<1;
    
  6. 大整数类与大整数类各运算对应的赋值运算

    Bign a,b;
    
    a*=b;
    
  7. 大整数类与大整数类大整数类与整型比较运算

    Bign a,b;ll c;
    
    if(a<=b || (a!=c && a>b))
    
  8. 大整数类 通过 cin、cout的输入输出

    Bign a;
    
    cin>>a;
    
    cout<<a+1<<endl;
    
  9. 整合负数的大整数类 取绝对值

    Bign a;
    
    cin>>a;
    
    cout<<abs(a)<<endl;
    

最大表示范围

\(\displaystyle 10^{\ \text{MX_LEN}\ *\ lg(\ \text{BASE}\ ) }\)​ ,默认是\(10^{1010*4}=10^{4040}\)​​​​


常量参数调整

(在使用时尽可能调整合适的常数以达到效率最高)

   const int MX_LEN=1010;

MX_LEN决定大整数类内数组大小,影响空间复杂度的主要因素,数值越大运算(越容易)越慢;同时也是储存数据范围的主要影响参数,在表示位数不够时请优先扩大MX_LEN。如果需要将MX_LEN改大,保险一点,一定一定要加上扩栈

   const int BASE=10000;

决定大整数类压位大小(BASE==每一个数组元素表示的最大值+1),请保证使用10的整数次幂,数值越大运算(总体上)越快。取值的原则是在“进行需要的运算时不会溢出对应数据类型”的条件下尽可能大。推荐使用10000 ( \(10^4\) ):既可使BASE尽可能大,同时保证两个大整数类进行乘法运算时不会溢出。

  1. 如果想把 num 的数据类型改成 long long 的话( long long num[MX_LEN] ) ,推荐 BASE 的取值是 1e8 或者 1e9
  2. 如果不需要使用乘法的话,不改 long long 的话,推荐 BASE 的取值是 1e8 或者 1e9
  3. 如果不需要使用乘法的话,改 long long 的话,推荐 BASE 的取值是 1e18 并也换成 long long 类型

注意

  1. 关于代码里的_max其实就是一个自己写的max,直接用max应该也是可以的
   #define _max(a,b) ((a)>(b)?(a):(b)) 
  1. 代码里有一部分循环变量使用了寄存器 register ,在代码里是简写为 R
   #define R register
  1. 在数据10^10000以上时需要手动扩栈:
   #pragma comment(linker, "/STACK:10240000,10240000")

模板代码

无负数版

const int BASE = 10000;
const int MX_LEN = 1010;
struct Bign {
    int num[MX_LEN];
    int len;
    Bign() {
        memset(num, 0, sizeof(num));
        len = 1;
    }
    Bign(const ll x) { *this = x; }
    Bign(const string x) { *this = x; }
    Bign(const Bign& x) {
        memset(num, 0, sizeof(num));
        len = x.len;
        for (int i = 0; i < len; i++)
            num[i] = x.num[i];
    }
    void clean() {
        while (num[len - 1] == 0 && len != 1)
            len--;
    }
    Bign operator = (const ll x) {
        stringstream ss;
        ss << x;
        string temp;
        ss >> temp;
        return *this = temp;
    }
    Bign operator = (const string x) {
        len = 0;
        memset(num, 0, sizeof(num));
        ll temp = 0;
        ll base = 1;
        for (int i = x.length() - 1; i >= 0; i--) {
            temp += (x[i] - '0') * base;
            base *= 10;
            if (base == BASE) {
                num[len++] = temp;
                temp = 0;
                base = 1;
            }
        }
        num[len++] = temp;
        clean();
        return *this;
    }
    Bign operator + (const Bign& b) const {
        Bign c;
        c.len = _max(len, b.len) + 1;
        for (int i = 0; i < c.len; i++) {
            c.num[i] += num[i] + b.num[i];
            c.num[i + 1] += c.num[i] / BASE;
            c.num[i] %= BASE;
        }
        c.clean();
        return c;
    }
    Bign operator - (const Bign& b) const {//a-b保证a>b
        Bign c;
        c.len = _max(len, b.len);
        for (int i = 0; i < c.len; ++i) {
            c.num[i] += num[i] - b.num[i];
            if (c.num[i] < 0) {
                c.num[i] += BASE;
                c.num[i + 1] -= 1;
            }
        }
        c.clean();
        return c;
    }
    Bign operator << (const int& num) const {
        Bign c = *this;
        c.len += 10;
        for (R int i = 0; i < c.len; ++i) {
            c.num[i] <<= num;
            if (i && c.num[i - 1] >= BASE)
                ++c.num[i], c.num[i - 1] -= BASE;
        }
        c.clean();
        return c;
    }
    Bign operator >> (const int& num) const {
        Bign c = *this;
        for (R int i = len - 1; i >= 0; --i) {
            if ((c.num[i] & 1) && i)
                c.num[i - 1] += BASE;
            c.num[i] >>= num;
        }
        c.clean();
        return c;
    }
    Bign operator * (const Bign& b) const {
        Bign c;
        c.len = len + b.len + 5;
        for (int i = 0; i < c.len; ++i) {
            for (int j = 0; j < b.len; ++j) {
                c.num[i + j] += num[i] * b.num[j];
                c.num[i + j + 1] += c.num[i + j] / BASE;
                c.num[i + j] %= BASE;
            }
        }
        c.clean();
        return c;
    }
    Bign operator / (const ll& b) const { //大数除以long long
        Bign c;
        c.len = len;
        ll rest = 0;
        for (int i = len - 1; i >= 0; --i) {
            rest = rest * BASE + num[i];
            c.num[i] = rest / b;
            rest %= b;
        }
        c.clean();
        return c;
    }
    Bign operator / (const Bign& b) const {
        Bign c, rest, now, _base;
        now = *this;
        rest = b;
        _base = 1;
        while (now >= rest) {
            rest = rest << 1;
            _base = _base << 1;
        }
        while (_base.len > 1 || _base.num[0]) {
            if (now >= rest) {
                now -= rest;
                c += _base;
            }
            rest = rest >> 1;
            _base = _base >> 1;
        }
        c.clean();
        return c;
    }
    Bign operator % (const ll& b) const {
        return (*this) - ((*this) / b) * b;
    }
    Bign operator % (const Bign& b) const {
        return (*this) - ((*this) / b) * b;
    }
    Bign operator += (const Bign& b) {
        return (*this) = (*this) + b;
    }
    Bign operator -= (const Bign& b) {
        return (*this) = (*this) - b;
    }
    Bign operator *= (const Bign& b) {
        return (*this) = (*this) * b;
    }
    Bign operator /= (const ll& b) {
        return (*this) = (*this) / b;
    }
    Bign operator /= (const Bign& b) {
        return (*this) = (*this) / b;
    }
    Bign operator %= (const ll& b) {
        return (*this) = (*this) % b;
    }
    Bign operator %= (const Bign& b) {
        return (*this) = (*this) % b;
    }
    bool operator < (const Bign& b) const {
        if (len == b.len) {
            for (int i = len - 1; i >= 0; --i) {
                if (num[i] != b.num[i])
                    return num[i] < b.num[i];
            }
            return 0;
        }
        return len < b.len;
    }
    bool operator > (const Bign& b) const {
        if (len == b.len) {
            for (int i = len - 1; i >= 0; --i) {
                if (num[i] != b.num[i])
                    return num[i] > b.num[i];
            }
            return 0;
        }
        return len > b.len;
    }
    bool operator == (const Bign& b) const {
        if (len == b.len) {
            for (int i = len - 1; i >= 0; --i) {
                if (num[i] != b.num[i])
                    return 0;
            }
            return 1;
        }
        return 0;
    }
    bool operator != (const Bign& b) const {
        return !((*this) == b);
    }
    bool operator <= (const Bign& b) const {
        return !((*this) > b);
    }
    bool operator >= (const Bign& b) const {
        return !((*this) < b);
    }
    friend ostream& operator << (ostream& out, const Bign& x) {
        out << x.num[x.len - 1];
        for (int i = x.len - 2; i >= 0; i--) {
            int t = BASE / 10;
            while (x.num[i] < t && t>1) {
                out << 0;
                t /= 10;
            }
            out << x.num[i];
        }
        return out;
    }
    friend istream& operator >> (istream& in, Bign& x) {
        string temp;
        in >> temp;
        x = temp;
        return in;
    }
};

整合负数版

const int BASE = 10000;
const int MX_LEN = 1010;
struct Bign {
    int num[MX_LEN];
    int len;
    int neg;
    Bign() {
        memset(num, 0, sizeof(num));
        len = 1;
        neg = 0;
    }
    Bign(const ll x) { *this = x; }
    Bign(const string x) { *this = x; }
    Bign(const Bign& x) {
        memset(num, 0, sizeof(num));
        len = x.len;
        neg = x.neg;
        for (R int i = 0; i < len; ++i)
            num[i] = x.num[i];
    }
    void clean() {
        while (num[len - 1] == 0 && len != 1)
            --len;
        if (len == 1 && num[0] == 0)
            neg = 0;
    }
    Bign operator = (const ll& x) {
        stringstream ss;
        ss << x;
        string temp;
        ss >> temp;
        return *this = temp;
    }
    Bign operator = (const string& x) {
        len = 0;
        memset(num, 0, sizeof(num));
        if (x[0] == '-')
            neg = 1;
        else
            neg = 0;
        ll temp = 0;
        ll base = 1;
        for (R int i = x.length() - 1; i >= neg; --i) {
            temp += (x[i] - '0') * base;
            base *= 10;
            if (base == BASE) {
                num[len++] = temp;
                temp = 0;
                base = 1;
            }
        }
        num[len++] = temp;
        clean();
        return *this;
    }
    Bign operator + (const Bign& b) const {
        if (neg ^ b.neg) {
            if (neg)
                return b - (-*this);
            else
                return (*this) - (-b);
        }
        else {
            Bign c;
            if (neg)
                c.neg = 1;
            c.len = _max(len, b.len) + 1;
            for (R int i = 0; i < c.len; ++i) {
                c.num[i] += num[i] + b.num[i];
                c.num[i + 1] += c.num[i] / BASE;
                c.num[i] %= BASE;
            }
            c.clean();
            return c;
        }
    }
    Bign operator - (const Bign& b) const {
        if (neg ^ b.neg) {
            if (neg)
                return -((-*this) + b);
            else
                return (*this) + (-b);
        }
        else {
            Bign c;
            if (neg)
                c.neg = 1;
            if (abs(*this) < abs(b)) {
                c.neg ^= 1;
                c.len = _max(len, b.len);
                for (R int i = 0; i < c.len; ++i) {
                    c.num[i] += b.num[i] - num[i];
                    if (c.num[i] < 0) {
                        c.num[i] += BASE;
                        c.num[i + 1] -= 1;
                    }
                }
                c.clean();
                return c;
            }
            else {
                c.len = _max(len, b.len);
                for (R int i = 0; i < c.len; ++i) {
                    c.num[i] += num[i] - b.num[i];
                    if (c.num[i] < 0) {
                        c.num[i] += BASE;
                        c.num[i + 1] -= 1;
                    }
                }
                c.clean();
                return c;
            }

        }
    }
    Bign operator - () const {
        Bign c = *this;
        c.neg ^= 1;
        return c;
    }
    Bign operator * (const Bign& b) const {
        Bign c;
        c.len = len + b.len + 1;
        for (R int i = 0; i < len; ++i) {
            for (R int j = 0; j < b.len; ++j) {
                c.num[i + j] += num[i] * b.num[j];
            }
        }
        for (R int i = 0; i < c.len; ++i) {
            c.num[i + 1] += c.num[i] / BASE;
            c.num[i] %= BASE;
        }
        if (neg ^ b.neg)
            c.neg = 1;
        c.clean();
        return c;
    }
    Bign operator / (const ll& b) const {
        Bign c;
        c.len = len;
        ll rest = 0;
        for (R int i = len - 1; i >= 0; --i) {
            rest = rest * BASE + num[i];
            c.num[i] = rest / b;
            rest %= b;
        }
        if (neg ^ (b < 0))
            c.neg = 1;
        c.clean();
        return c;
    }
    Bign operator / (const Bign& b) const {
        Bign c, rest, now, _base;
        now = abs(*this);
        rest = abs(b);
        _base = 1;
        while (now >= rest) {
            rest <<= 1;
            _base <<= 1;
        }
        while (_base.len > 1 || _base.num[0]) {
            if (now >= rest) {
                now -= rest;
                c += _base;
            }
            rest >>= 1;
            _base >>= 1;
        }
        if (neg ^ b.neg)
            c.neg = 1;
        c.clean();
        return c;
    }
    Bign operator << (const int& num) const {
        Bign c = *this;
        c.len += 10;
        for (R int i = 0; i < c.len; ++i) {
            c.num[i] <<= num;
            if (i && c.num[i - 1] >= BASE)
                ++c.num[i], c.num[i - 1] -= BASE;
        }
        c.clean();
        return c;
    }
    Bign operator >> (const int& num) const {
        Bign c = *this;
        for (R int i = len - 1; i >= 0; --i) {
            if ((c.num[i] & 1) && i)
                c.num[i - 1] += BASE;
            c.num[i] >>= num;
        }
        c.clean();
        return c;
    }
    Bign operator % (const ll& b) const {
        return (*this) - ((*this) / b) * b;
    }
    Bign operator % (const Bign& b) const {
        return (*this) - ((*this) / b) * b;
    }
    Bign operator += (const Bign& b) {
        return (*this) = (*this) + b;
    }
    Bign operator -= (const Bign& b) {
        return (*this) = (*this) - b;
    }
    Bign operator *= (const Bign& b) {
        return (*this) = (*this) * b;
    }
    Bign operator /= (const ll& b) {
        return (*this) = (*this) / b;
    }
    Bign operator /= (const Bign& b) {
        return (*this) = (*this) / b;
    }
    Bign operator %= (const ll& b) {
        return (*this) = (*this) % b;
    }
    Bign operator %= (const Bign& b) {
        return (*this) = (*this) % b;
    }
    Bign operator <<= (const int& num) {
        return (*this) = (*this) << num;
    }
    Bign operator >>= (const int& num) {
        return (*this) = (*this) >> num;
    }
    bool operator < (const Bign& b) const {
        if (neg && !b.neg)
            return 1;
        if (!neg && b.neg)
            return 0;
        if (neg) {
            if (len == b.len) {
                for (R int i = len - 1; i >= 0; --i) {
                    if (num[i] != b.num[i])
                        return num[i] > b.num[i];
                }
                return 0;
            }
            return len > b.len;
        }
        else {
            if (len == b.len) {
                for (R int i = len - 1; i >= 0; --i) {
                    if (num[i] != b.num[i])
                        return num[i] < b.num[i];
                }
                return 0;
            }
            return len < b.len;
        }
    }
    bool operator > (const Bign& b) const {
        if (neg && !b.neg)
            return 0;
        if (!neg && b.neg)
            return 1;
        if (neg) {
            if (len == b.len) {
                for (R int i = len - 1; i >= 0; --i) {
                    if (num[i] != b.num[i])
                        return num[i] < b.num[i];
                }
                return 0;
            }
            return len < b.len;
        }
        else {
            if (len == b.len) {
                for (R int i = len - 1; i >= 0; --i) {
                    if (num[i] != b.num[i])
                        return num[i] > b.num[i];
                }
                return 0;
            }
            return len > b.len;
        }
    }
    bool operator == (const Bign& b) const {
        if (neg != b.neg)
            return 0;
        if (len == b.len) {
            for (R int i = len - 1; i >= 0; --i) {
                if (num[i] != b.num[i])
                    return 0;
            }
            return 1;
        }
        return 0;
    }
    bool operator != (const Bign& b) const {
        return !((*this) == b);
    }
    bool operator <= (const Bign& b) const {
        return !((*this) > b);
    }
    bool operator >= (const Bign& b) const {
        return !((*this) < b);
    }
    friend Bign abs(const Bign& x) {
        Bign c = x;
        c.neg = 0;
        return c;
    }
    friend ostream& operator << (ostream& out, const Bign& x) {
        if (x.neg)
            out << '-';
        out << x.num[x.len - 1];
        for (R int i = x.len - 2; i >= 0; --i) {
            int t = BASE / 10;
            while (x.num[i] < t && t>1) {
                out << 0;
                t /= 10;
            }
            out << x.num[i];
        }
        return out;
    }
    friend istream& operator >> (istream& in, Bign& x) {
        string temp;
        in >> temp;
        x = temp;
        return in;
    }
};
posted @ 2021-08-12 19:59  RagnaLP  阅读(66)  评论(0编辑  收藏  举报