Computing with huge integer

来源:互联网 发布:matlab 2015b mac 编辑:程序博客网 时间:2024/04/29 18:52

 This article is came from a discussion in forum, it is a problem to computing f(n) that f(n) = fibonacci[i-1]*fibonacci[i]*fibonacci[i+1]. Apparently the vaule of f(n) is too huge to represented by primitive type such as double. So it is requiring to introducing a mechanism to supplying huge integer. Here I use string but the most effective and convenient way is introducing numeric library. My codes follows(it is just a example, if the effective requirement is a bit rigorous, knowledge about numberical algorithm must be equipped):

#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;

string add(const string& a, const string& b)
{
    string temp, min, max;
    int min_length, max_length = 0;

    if(a.size()<b.size())
    {  
        min = a; max = b;
        min_length = a.size();
        max_length = b.size();
    }
    else
    {
        min = b; max = a;
        min_length = b.size();
        max_length = a.size();
    }
    temp.reserve(max_length + 1);
    int t, adv;
    t, adv = 0;
    for(int i = 0; i<min_length; ++i)
    {
        t = min[min_length-i-1]-'0' + max[max_length-i-1]-'0' + adv;
        if(t>9)
        {
                temp.push_back(t - 10 + '0');
                adv = 1;
        }
        else
        {
                temp.push_back(t + '0');
                adv = 0;
        }
    }
    if(min_length == max_length)
    {
        if(adv == 1)
            temp.push_back(adv + '0');
    }
    else
    {
        for(int i = min_length; i<max_length; ++i)
        {
            t = max[max_length-i-1]-'0' + adv;
            if(t>9)
            {
                    temp.push_back(t - 10 + '0');
                    adv = 1;
            }
            else
            {
                    temp.push_back(t + '0');
                    adv = 0;
            }
        }
        if(adv == 1)
            temp.push_back(adv + '0');
    }
    reverse(temp.begin(), temp.end());
    return temp;
}
string mul(const string& a, const string& b)
{
    string min, max;
    string temp((a.size() + b.size()), '0');
    int min_length, max_length = 0;
    if(a.size()<b.size())
    {  
        min = a; max = b;
        min_length = a.size();
        max_length = b.size();
    }
    else
    {
        min = b; max = a;
        min_length = b.size();
        max_length = a.size();
    }
    int i, j, t, adv, pos;
    for(i = min_length-1; i>=0; --i)
    {
        adv=0; 
        for(j = max_length-1; j>=0; --j)
        {
            pos = i + j + 1; 
            t = (min[i]-'0')*(max[j]-'0') + temp[pos]-'0' + adv; 
            adv = t/10; 
            t = t%10; 
            temp[pos] = t + '0'; 
        }
        if(adv > 0)
           temp[i+j+1] = adv + '0'; 
    }
    int eliminate_zeros_num = 0;
    for(; temp[eliminate_zeros_num] == '0'; ++eliminate_zeros_num); // eliminate 0 appeard in head. i.e. 15*2=30.but temp will be init by 000 that is 3 digits
    return temp.substr(eliminate_zeros_num);
}

bool l_less_r(const string& a, const string& b)
{
    if(a.size() < b.size())
        return true;
    else if(a.size() > b.size())
        return false;
    else
        return a<b;
}

class caculate_f
{
    vector<string> known;
    string fib(int i)
    {
        string t;
        if(known[i] != "0")
            return known[i];
        if(i == 0) t = "0";
        if(i == 1) t = "1";
        if(i > 1) t = add(fib(i-1), fib(i-2));
        known[i] = t;
        return known[i];
    }
public:
    caculate_f(int n, string& p):known(n+1, "0")
    {
        fib(n);
        cacu_f(n, p);
    }
    void cacu_f(int i, string& res)
    {
        string t = mul(known[i-2], known[i-1]);
        res = mul(known[i], t);
    }
};
int main(int argc, char* argv[])
{
    string res;
    caculate_f a(1000, res);
    cout<<res;
    system("pause");
    return 0;
}

原创粉丝点击