Monday, 25 November 2013

BigInteger Program in C++

Once I was searching for BigInteger programs in C++, then I found this one. I really don't remember the source, as I copied it then.
But now as I am using this program for many problems, I thought of adding this one as it is really good.

If you use Java or python, you will never need this program.
















// The BigInteger Ripper

#include <vector>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
typedef long long LL;
// base and base_digits must be consistent
const int base = 1000000000;
const int base_digits = 9;

struct bigint {
    vector<int> a;
    int sign;

    bigint() :
        sign(1) {
    }

    bigint(long long v) {
        *this = v;
    }

    bigint(const string &s) {
        read(s);
    }

    void operator=(const bigint &v) {
        sign = v.sign;
        a = v.a;
    }

    void operator=(long long v) {
        sign = 1;
        if (v < 0)
            sign = -1, v = -v;
        for (; v > 0; v = v / base)
            a.push_back(v % base);
    }

    bigint operator+(const bigint &v) const {
        if (sign == v.sign) {
            bigint res = v;

            for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
                if (i == (int) res.a.size())
                    res.a.push_back(0);
                res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
                carry = res.a[i] >= base;
                if (carry)
                    res.a[i] -= base;
            }
            return res;
        }
        return *this - (-v);
    }

    bigint operator-(const bigint &v) const {
        if (sign == v.sign) {
            if (abs() >= v.abs()) {
                bigint res = *this;
                for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
                    res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
                    carry = res.a[i] < 0;
                    if (carry)
                        res.a[i] += base;
                }
                res.trim();
                return res;
            }
            return -(v - *this);
        }
        return *this + (-v);
    }

    void operator*=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
            if (i == (int) a.size())
                a.push_back(0);
            long long cur = a[i] * (long long) v + carry;
            carry = (int) (cur / base);
            a[i] = (int) (cur % base);
            //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
        }
        trim();
    }

    bigint operator*(int v) const {
        bigint res = *this;
        res *= v;
        return res;
    }

    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
        int norm = base / (b1.a.back() + 1);
        bigint a = a1.abs() * norm;
        bigint b = b1.abs() * norm;
        bigint q, r;
        q.a.resize(a.a.size());

        for (int i = a.a.size() - 1; i >= 0; i--) {
            r *= base;
            r += a.a[i];
            int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
            int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
            int d = ((long long) base * s1 + s2) / b.a.back();
            r -= b * d;
            while (r < 0)
                r += b, --d;
            q.a[i] = d;
        }

        q.sign = a1.sign * b1.sign;
        r.sign = a1.sign;
        q.trim();
        r.trim();
        return make_pair(q, r / norm);
    }

    bigint operator/(const bigint &v) const {
        return divmod(*this, v).first;
    }

    bigint operator%(const bigint &v) const {
        return divmod(*this, v).second;
    }

    void operator/=(int v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
            long long cur = a[i] + rem * (long long) base;
            a[i] = (int) (cur / v);
            rem = (int) (cur % v);
        }
        trim();
    }

    bigint operator/(int v) const {
        bigint res = *this;
        res /= v;
        return res;
    }

    int operator%(int v) const {
        if (v < 0)
            v = -v;
        int m = 0;
        for (int i = a.size() - 1; i >= 0; --i)
            m = (a[i] + m * (long long) base) % v;
        return m * sign;
    }

    void operator+=(const bigint &v) {
        *this = *this + v;
    }
    void operator-=(const bigint &v) {
        *this = *this - v;
    }
    void operator*=(const bigint &v) {
        *this = *this * v;
    }
    void operator/=(const bigint &v) {
        *this = *this / v;
    }

    bool operator<(const bigint &v) const {
        if (sign != v.sign)
            return sign < v.sign;
        if (a.size() != v.a.size())
            return a.size() * sign < v.a.size() * v.sign;
        for (int i = a.size() - 1; i >= 0; i--)
            if (a[i] != v.a[i])
                return a[i] * sign < v.a[i] * sign;
        return false;
    }

    bool operator>(const bigint &v) const {
        return v < *this;
    }
    bool operator<=(const bigint &v) const {
        return !(v < *this);
    }
    bool operator>=(const bigint &v) const {
        return !(*this < v);
    }
    bool operator==(const bigint &v) const {
        return !(*this < v) && !(v < *this);
    }
    bool operator!=(const bigint &v) const {
        return *this < v || v < *this;
    }

    void trim() {
        while (!a.empty() && !a.back())
            a.pop_back();
        if (a.empty())
            sign = 1;
    }

    bool isZero() const {
        return a.empty() || (a.size() == 1 && !a[0]);
    }

    bigint operator-() const {
        bigint res = *this;
        res.sign = -sign;
        return res;
    }

    bigint abs() const {
        bigint res = *this;
        res.sign *= res.sign;
        return res;
    }

    long long longValue() const {
        long long res = 0;
        for (int i = a.size() - 1; i >= 0; i--)
            res = res * base + a[i];
        return res * sign;
    }

    friend bigint gcd(const bigint &a, const bigint &b) {
        return b.isZero() ? a : gcd(b, a % b);
    }
    friend bigint lcm(const bigint &a, const bigint &b) {
        return a / gcd(a, b) * b;
    }

    void read(const string &s) {
        sign = 1;
        a.clear();
        int pos = 0;
        while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-')
                sign = -sign;
            ++pos;
        }
        for (int i = s.size() - 1; i >= pos; i -= base_digits) {
            int x = 0;
            for (int j = max(pos, i - base_digits + 1); j <= i; j++)
                x = x * 10 + s[j] - '0';
            a.push_back(x);
        }
        trim();
    }
   
    int length(){
    int l=0,back=a.back();
    while(back){l++;back/=10;}
    l+=((a.size()-1)*base_digits);
    return l;
    }

    friend istream& operator>>(istream &stream, bigint &v) {
        string s;
        stream >> s;
        v.read(s);
        return stream;
    }

    friend ostream& operator<<(ostream &stream, const bigint &v) {
        if (v.sign == -1)
            stream << '-';
        stream << (v.a.empty() ? 0 : v.a.back());
        for (int i = (int) v.a.size() - 2; i >= 0; --i)
            stream << setw(base_digits) << setfill('0') << v.a[i];
        return stream;
    }

    static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
        vector<long long> p(max(old_digits, new_digits) + 1);
        p[0] = 1;
        for (int i = 1; i < (int) p.size(); i++)
            p[i] = p[i - 1] * 10;
        vector<int> res;
        long long cur = 0;
        int cur_digits = 0;
        for (int i = 0; i < (int) a.size(); i++) {
            cur += a[i] * p[cur_digits];
            cur_digits += old_digits;
            while (cur_digits >= new_digits) {
                res.push_back(int(cur % p[new_digits]));
                cur /= p[new_digits];
                cur_digits -= new_digits;
            }
        }
        res.push_back((int) cur);
        while (!res.empty() && !res.back())
            res.pop_back();
        return res;
    }

    typedef vector<long long> vll;

    static vll karatsubaMultiply(const vll &a, const vll &b) {
        int n = a.size();
        vll res(n + n);
        if (n <= 32) {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                    res[i + j] += a[i] * b[j];
            return res;
        }

        int k = n >> 1;
        vll a1(a.begin(), a.begin() + k);
        vll a2(a.begin() + k, a.end());
        vll b1(b.begin(), b.begin() + k);
        vll b2(b.begin() + k, b.end());

        vll a1b1 = karatsubaMultiply(a1, b1);
        vll a2b2 = karatsubaMultiply(a2, b2);

        for (int i = 0; i < k; i++)
            a2[i] += a1[i];
        for (int i = 0; i < k; i++)
            b2[i] += b1[i];

        vll r = karatsubaMultiply(a2, b2);
        for (int i = 0; i < (int) a1b1.size(); i++)
            r[i] -= a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            r[i] -= a2b2[i];

        for (int i = 0; i < (int) r.size(); i++)
            res[i + k] += r[i];
        for (int i = 0; i < (int) a1b1.size(); i++)
            res[i] += a1b1[i];
        for (int i = 0; i < (int) a2b2.size(); i++)
            res[i + n] += a2b2[i];
        return res;
    }

    bigint operator*(const bigint &v) const {
        vector<int> a6 = convert_base(this->a, base_digits, 6);
        vector<int> b6 = convert_base(v.a, base_digits, 6);
        vll a(a6.begin(), a6.end());
        vll b(b6.begin(), b6.end());
        while (a.size() < b.size())
            a.push_back(0);
        while (b.size() < a.size())
            b.push_back(0);
        while (a.size() & (a.size() - 1))
            a.push_back(0), b.push_back(0);
        vll c = karatsubaMultiply(a, b);
        bigint res;
        res.sign = sign * v.sign;
        for (int i = 0, carry = 0; i < (int) c.size(); i++) {
            long long cur = c[i] + carry;
            res.a.push_back((int) (cur % 1000000));
            carry = (int) (cur / 1000000);
        }
        res.a = convert_base(res.a, 6, base_digits);
        res.trim();
        return res;
    }
};


void recursive_fraction(bigint a,bigint b)
{
  bigint n,i;
  if(a>b)
  {
    n=a/b;
    for(i=1;i<=n;i+=1)
    {
       cout<<"1 ";
    }
    a=(a-b*n);
  }
  while(a!=0)
  {
    n=b/a;
    if(b%a!=0) n=n+1;
    cout<<n<<" ";
    a=n*a-b;
    b=n*b;
  }
}
int main()
{
 while(true)
 {
      bigint num;
      cin>>num;
      if(num == -1)break;
      bigint nine = 9;
      bigint ans = num/nine;
      bigint zero = 0;
      if(num%nine != zero)
             ans = ans + 1;
      cout<<ans<<endl;
 }
  return 0;
}


PS: (My implementation of Biginteger add, multiply and subtraction, just coded it once in the beginning)

// My Implementation

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
typedef long long int int64;
using namespace std;
char op1[100001],op2[100001],res[200003];

char * convert(int64 a,char * num)
{
     int len = int(log10(double(a)));
     num[len+1] = '\0';
     while(a>0)
     {
      num[len--] = a%10 + '0';
      a = a/10;        
     }
     return num;
}

char * convert(char * a,char * num)
{
     strcpy(num,a);
     return num;
}

char * reverse(char * num)
{
 char x[200003];int lo = 0;
 int len = strlen(num);
 while(num[len-1]=='0' && len>=1)
                       len--;

 if(len==0)
           {num[0]='0';num[1]='\0';return num;}

 for(int xx = len-1;xx>=0;xx--)
 {
         x[lo++] = num[xx];
 }  
 x[lo]='\0';
 strcpy(num,x);
 return num;
}

char * add(char * a, char * b, char * num)
{
     int len1 = strlen(a)-1;
     int len2 = strlen(b)-1;
     int carry = 0;
     int x = 0;
     while(len1>=0 && len2>=0)
     {
      int temp = a[len1--]-'0'+ b[len2--]-'0' + carry;            
      num[x++] = temp%10 + '0';
      carry = temp/10;
     }   
     while(len1>=0)
     {
      int temp = a[len1--]-'0'+ carry;            
      num[x++] = temp%10 + '0';
      carry = temp/10;
     }
     while(len2>=0)
     {
      int temp = b[len2--]-'0'+ carry;            
      num[x++] = temp%10 + '0';
      carry = temp/10;
     }
     if(carry>0)
                num[x++] = carry+'0';
     num[x] = '\0';   
     return reverse(num);
}

char * sub(char * a, char * b, char * num)
{
     int len1 = strlen(a)-1;
     int len2 = strlen(b)-1;
     int carry = 0;
     int x = 0;int togl = 0;
     while(len2>=0)
     {
      int temp;
      if(a[len1]>=b[len2])
      {
       temp = a[len1] - b[len2];
       num[x++] = temp + '0';                   
       len1--,len2--;
      }
      else
      {
       int flag;togl = 1;
       while(a[len1]<=b[len2])
       {
        if(togl==1){num[x++] = a[len1] - b[len2]+10 +'0';togl=0;}
        else {num[x++] = a[len1] - b[len2]+9 +'0';}
        len1--,len2--;            
        if(len2<0)
                  {flag=1;break;} 
       }  
       while(a[len1]=='0'){num[x++]='9';len1--;}
       num[x++] =    a[len1] - (flag==1?'0':b[len2]) - 1 +'0';
       len2--,len1--;
      }            
     }
     while(len1>=0)
                   num[x++]=a[len1--];
     num[x]= '\0';

     return reverse(num);
}


char * mult(char * a, char * b, char * num)
{
     int len1 = strlen(a)-1;
     int len2 = strlen(b)-1;
     int x=0,carry=0,ll=0,mm=0,prevll=-1;
     for(int i=len1;i>=0;i--)
     {
      int mul1 = a[i]-'0';
      for(int j=len2;j>=0;j--)      
             {
                int mul2 = b[j]-'0';          
                int temp = mul1*mul2 + carry + (mm<=prevll?num[mm]-'0':0);
                num[mm++] = temp%10 +'0';
                carry = temp/10;                                    
             }
             if(carry>0)
                        {num[mm++]=carry+'0';
                         carry = 0;}
             prevll = mm-1;
             ll++;
             if(i==0){num[mm]='\0';break;}
             mm = ll;
     }
     return reverse(num);
}



int main()
{
 char a[100001], b[100001];
 while(cin>>a>>b)
 {
  //cout<<add(convert(a,op1),convert(b,op2),res)<<endl;
  cout<<sub(convert(a,op1),convert(b,op2),res)<<endl;
  //cout<<mult(convert(a,op1),convert(b,op2),res)<<endl; 
 
 }
return 0;
}

18 comments:


  1. Thanks you for sharing the unique content. you have done a great job. thank you for sharing such a unique content.
    Linux Training in Chennai

    ReplyDelete
  2. Awesome article. It is so detailed and well formatted that i enjoyed reading it as well as get some new information too.


    SAP HR training in Chennai

    ReplyDelete
  3. I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work..

    SAT coaching chennai | SAT training centre in chennai

    ReplyDelete
  4. you are posting a good information for people and keep maintain and give

    more updates too.

    seo company india

    ReplyDelete
  5. very very amazing explaintion....many things gather about yourself...yes realy i enjoy it
    Base SAS Training in Chennai

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Have you been thinking about the power sources and the tiles whom use blocks I wanted to thank you for this great read!! I definitely enjoyed every little bit of it and I have you bookmarked to check out the new stuff you post
    rpa training in bangalore
    best rpa training in bangalore
    rpa training in pune

    ReplyDelete
  8. It's interesting that many of the bloggers to helped clarify a few things for me as well as giving.
    Most of ideas can be nice content.The people to give them a good shake to get your point and across the command.
    Java training in Chennai
    Java training in Bangalore
    Java online training
    Java training in Pune

    ReplyDelete
  9. It’s really great information for becoming a better Blogger. Keep sharing, Thanks...

    Learn Hadoop Training from the Industry Experts we bridge the gap between the need of the industry. Softgen Infotech provide the Best Hadoop Training in Bangalore with 100% Placement Assistance. Book a Free Demo Today.
    Big Data Analytics Training in Bangalore
    Tableau Training in Bangalore
    Data Science Training in Bangalore
    Workday Training in Bangalore

    ReplyDelete
  10. I must appreciate you for providing such a valuable content for us. This is one amazing piece of article. Helped a lot in increasing my knowledge.Wonderful Post. the Post is very clear and explains the Content neatly in manner.

    Data Science Training In Chennai

    Data Science Online Training In Chennai

    Data Science Training In Bangalore

    Data Science Training In Hyderabad

    Data Science Training In Coimbatore

    Data Science Training

    Data Science Online Training

    ReplyDelete