AlexeiBishop's blog

By AlexeiBishop, history, 6 years ago, In Russian

class BigInteger { public: BigInteger() { _data.push_back(0); }

BigInteger(long long x)
{
    while(x)
    {
        _data.push_back(x % _base);
        x /= _base;
    }

    if(_data.empty()) _data.push_back(0);
}

BigInteger(unsigned long long x)
{
    while(x)
    {
        _data.push_back(x % _base);
        x /= _base;
    }

    if(_data.empty()) _data.push_back(0);
}

BigInteger(int x) : BigInteger((long long)x) {}
BigInteger(unsigned int x) : BigInteger((unsigned long long)x) {}
BigInteger(short x) : BigInteger((long long)x) {}
BigInteger(unsigned short x) : BigInteger((unsigned long long)x) {}
BigInteger(char x) : BigInteger((long long)x) {}
BigInteger(unsigned char x) : BigInteger((unsigned long long)x) {}

BigInteger(std::string &s)
{
    for(int i = (int)s.size(); i > 0; i -= 9)
        if(i < 9)
            _data.push_back(atoi(s.substr(0, i).data()));
        else
            _data.push_back(atoi(s.substr(i - 9, 9).data()));

    while(_data.size() > 1 && _data.back() == 0)
        _data.pop_back();
}

BigInteger(const char *s)  
{
    std::string d = s;

    for(int i = (int)d.size(); i > 0; i -= 9)
        if(i < 9)
            _data.push_back(atoi(d.substr(0, i).data()));
        else
            _data.push_back(atoi(d.substr(i - 9, 9).data()));

    while(_data.size() > 1 && _data.back() == 0)
        _data.pop_back();
}

BigInteger(const BigInteger& b)
{
    _data.resize(b._data.size());
    std::copy(b._data.begin(), b._data.end(), _data.begin());
}

void ToString(char *s) const
{
    sprintf(s, "%d", _data.empty() ? 0 : _data.back());
    for(int i = (int)_data.size() - 2; i >= 0; i--)
        sprintf(s, "%s%09d", s, _data[i]);
}

std::string ToString() const
{
    char *buff = (char*)malloc(20);

    sprintf(buff, "%d", _data.empty() ? 0 : _data.back());
    std::string res = buff;

    for(int i = (int)_data.size() - 2; i >= 0; i--)
    {
        sprintf(buff, "%09d", _data[i]);
        res += buff;
    }

    free(buff);

    return res;
}

friend const BigInteger operator+(BigInteger &i);
friend const BigInteger& operator++(BigInteger &i);
friend const BigInteger& operator--(BigInteger &i);
friend const BigInteger operator++(BigInteger &i, int);
friend const BigInteger operator--(BigInteger &i, int);

friend const BigInteger operator+(const BigInteger &c, const BigInteger &b);
friend const BigInteger operator-(const BigInteger &c, const BigInteger &b);
friend const BigInteger operator*(const BigInteger &a, const BigInteger &b);
friend const BigInteger operator/(const BigInteger &a, const BigInteger &b);
friend const BigInteger operator%(const BigInteger &a, const BigInteger &b);

friend BigInteger& operator+=(BigInteger &a, const BigInteger &b);
friend BigInteger& operator-=(BigInteger &a, const BigInteger &b);
friend BigInteger& operator*=(BigInteger &a, const BigInteger &b);
friend BigInteger& operator/=(BigInteger &a, const BigInteger &b);
friend BigInteger& operator%=(BigInteger &a, const BigInteger &b);

friend bool operator==(const BigInteger &a, const BigInteger &b);
friend bool operator<=(const BigInteger &a, const BigInteger &b);
friend bool operator>=(const BigInteger &a, const BigInteger &b);
friend bool operator<(const BigInteger &a, const BigInteger &b);
friend bool operator>(const BigInteger &a, const BigInteger &b);
friend bool operator!=(const BigInteger &a, const BigInteger &b);

/*operator long long() const
{
    long long res = 0, b = 1;
    for(size_t i = 0; i < _data.size(); i++)
    {
        res += b * _data[i];
        b *= BigInteger::_base;
    }
    return res;
}

operator unsigned long long()
{
    unsigned long long res = 0, b = 1;
    for(size_t i = 0; i < _data.size(); i++)
    {
        res += b * _data[i];
        b *= BigInteger::_base;
    }
    return res;
}*/

friend std::istream& operator>>(std::istream &is, BigInteger &i)
{
    std::string s;
    is >> s;
    i = BigInteger(s);
    return is;
}

friend std::ostream& operator<<(std::ostream &os, const BigInteger &i)
{
    os << i.ToString();
    return os;
}

private: static const int _base = 1000 * 1000 * 1000; std::vector _data;

int _cmp(const BigInteger &a, const BigInteger &b) const //a - b, 1 if a > b
{
    if(a._data.size() > b._data.size()) return 1;
    if(a._data.size() < b._data.size()) return -1;

    for(int i = (int)a._data.size() - 1; i >= 0; i--)
    {
        if(a._data[i] > b._data[i]) return 1;
        if(a._data[i] < b._data[i]) return -1;
    }

    return 0;
}

BigInteger _div_short(const BigInteger &c, int b, int &mod) const
{
    mod = 0;
    BigInteger a = c;
    for(int i = (int)a._data.size() - 1; i >= 0; i--) 
    {
        long long cur = a._data[i] + mod * 1ll * BigInteger::_base;
        a._data[i] = int(cur / b);
        mod = int(cur % b);
    }

    while (a._data.size() > 1 && a._data.back() == 0)
        a._data.pop_back();

    return a;
}

bool _is_zero() const
{
    return _data.size() == 1 && _data[0] == 0;
}

};

const BigInteger operator+(const BigInteger &i) { return BigInteger(i); }

const BigInteger& operator++(BigInteger &i) { int j = 0; i._data[0]++;

while(i._data[j] >= BigInteger::_base)
{
    if(j == (int)i._data.size() - 1) i._data.push_back(1); else i._data[j + 1]++;
    i._data[j] -= BigInteger::_base;
    j++;
}

return i;

}

const BigInteger operator++(BigInteger &i, int) { BigInteger old = BigInteger(i);

int j = 0;
i._data[0]++;

while(i._data[j] >= BigInteger::_base)
{
    if(j == (int)i._data.size() - 1) i._data.push_back(1); else i._data[j + 1]++;
    i._data[j] -= BigInteger::_base;
    j++;
}

return old;

}

//TODO: Optimize const BigInteger& operator--(BigInteger &i) { if(!i._is_zero()) i = i — 1; return i; }

//TODO: Optimize const BigInteger operator--(BigInteger &i, int) { BigInteger old = BigInteger(i); if(!i._is_zero()) i = i — 1; return old; }

const BigInteger operator+(const BigInteger &c, const BigInteger &b) { BigInteger a = c;

int carry = 0;
for(size_t i = 0; i < std::max(a._data.size(), b._data.size()) || carry; i++) 
{
    if(i == a._data.size()) a._data.push_back(0);
    a._data[i] += carry + (i < b._data.size() ? b._data[i] : 0);
    carry = a._data[i] >= BigInteger::_base;
    if(carry) a._data[i] -= BigInteger::_base;
}   

return a;

}

const BigInteger operator-(const BigInteger &c, const BigInteger &b) { if(c < b) throw std::invalid_argument("a — b, a must b greater or equal zero"); BigInteger a = c;

int carry = 0;
for(size_t i = 0; i < b._data.size() || carry; i++) 
{
    a._data[i] -= carry + (i < b._data.size() ? b._data[i] : 0);
    carry = a._data[i] < 0;
    if(carry) a._data[i] += BigInteger::_base;
}

while(a._data.size() > 1 && a._data.back() == 0)
    a._data.pop_back();

return a;

}

const BigInteger operator*(const BigInteger &a, const BigInteger &b) { BigInteger c; c._data.resize(a._data.size() + b._data.size());

for(size_t i = 0; i < a._data.size(); i++)
    for(int j = 0, carry = 0; j < (int)b._data.size() || carry; j++) 
    {
        long long cur = c._data[i + j] + a._data[i] * 1ll * (j < (int)b._data.size() ? b._data[j] : 0) + carry;
        c._data[i + j] = int(cur % BigInteger::_base);
        carry = int(cur / BigInteger::_base);
    }

while(c._data.size() > 1 && c._data.back() == 0)
    c._data.pop_back();

return c;

}

//TODO: Division by zero const BigInteger operator/(const BigInteger &a, const BigInteger &b) { if(b._is_zero()) throw std::invalid_argument("division by zero"); BigInteger l = 0, r = a + 1, m; int t; while(r — l > 1) { //m = (r + l) / 2; m = a._div_short(r + l, 2, t); if(b * m <= a) l = m; else r = m; } return l; }

//TODO: Division by zero const BigInteger operator%(const BigInteger &a, const BigInteger &b) { if(b._is_zero()) throw std::invalid_argument("division by zero"); BigInteger l = 0, r = a + 1, m; int t; while(r — l > 1) { //m = (r + l) / 2; m = a._div_short(r + l, 2, t); if(b * m <= a) l = m; else r = m; } return a — b * l; }

BigInteger& operator+=(BigInteger &a, const BigInteger &b) { int carry = 0; for(size_t i = 0; i < std::max(a._data.size(), b._data.size()) || carry; i++) { if(i == a._data.size()) a._data.push_back(0); a._data[i] += carry + (i < b._data.size() ? b._data[i] : 0); carry = a._data[i] >= BigInteger::_base; if(carry) a._data[i] -= BigInteger::_base; }
return a; }

BigInteger& operator-=(BigInteger &a, const BigInteger &b) { int carry = 0; for(size_t i = 0; i < b._data.size() || carry; i++) { a._data[i] -= carry + (i < b._data.size() ? b._data[i] : 0); carry = a._data[i] < 0; if(carry) a._data[i] += BigInteger::_base; }

while(a._data.size() > 1 && a._data.back() == 0)
    a._data.pop_back();

return a;

}

BigInteger& operator*=(BigInteger &a, const BigInteger &b) { a = a * b; return a; }

BigInteger& operator/=(BigInteger &a, const BigInteger &b) { a = a / b; return a; }

BigInteger& operator%=(BigInteger &a, const BigInteger &b) { a = a % b; return a; }

bool operator==(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) == 0; }

bool operator<=(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) <= 0; }

bool operator>=(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) >= 0; }

bool operator<(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) < 0; }

bool operator>(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) > 0; }

bool operator!=(const BigInteger& a, const BigInteger& b) { return a._cmp(a, b) != 0; }

  • Vote: I like it
  • -36
  • Vote: I do not like it