Skip to content

Instantly share code, notes, and snippets.

@gnitnaw
Last active August 29, 2015 14:21
Show Gist options
  • Save gnitnaw/79ccbac48a22e14b67c4 to your computer and use it in GitHub Desktop.
Save gnitnaw/79ccbac48a22e14b67c4 to your computer and use it in GitHub Desktop.
Class to estimate extra long number
#include <vector>
#include <iostream>
#include <sstream>
#include <math.h>
#include <sys/time.h>
using namespace std;
class BigNumber {
private :
vector <unsigned long> blocks;
static const unsigned long limitBlock = 10000000000;
const unsigned int nB = log10l(limitBlock);
public :
BigNumber(unsigned long n){
blocks.push_back(n%limitBlock);
if (n>=limitBlock) blocks.push_back(n/limitBlock);
}
size_t getNBlocks() const {
return blocks.size();
}
string getStringBlock(size_t i) const{
stringstream ss;
ss << blocks[i];
string convert_str;
ss >> convert_str;
if (blocks.size() == 1) return convert_str;
else {
if (i == blocks.size()-1) return convert_str;
else {
if (blocks[i]==0) {
for (unsigned int j(0); j<nB-1; ++j) {
convert_str += "0";
}
} else if (convert_str.size() < nB) {
for (unsigned int j(0); j<=(nB-convert_str.size()); ++j) {
convert_str = "0" + convert_str;
}
}
}
return convert_str;
}
}
int getNDigit() const {
int a=0;
for (size_t i(0); i<blocks.size(); ++i) {
a += getStringBlock(i).size();
}
return a;
}
void print(ostream& out) const {
for (int i(blocks.size()-1); i>=0; --i) {
cout << getStringBlock(i);
}
}
void Carry() {
for (unsigned int i(0); i<blocks.size(); ++i){
if (blocks[i]>=limitBlock) {
if (i!=blocks.size()-1) {
blocks[i+1] += blocks[i]/limitBlock;
} else {
blocks.push_back(blocks[i]/limitBlock);
}
blocks[i] = blocks[i]%limitBlock;
}
}
}
void Pop() {
while (blocks[getNBlocks()-1] == 0) {
blocks.pop_back();
}
}
BigNumber& operator+=(const BigNumber& c) {
while (c.getNBlocks()>blocks.size()) {
blocks.push_back(0);
}
for (unsigned int i(0); i<c.getNBlocks(); ++i) {
blocks[i]+=c.blocks[i];
}
Carry();
return *this;
}
BigNumber& operator-=(const BigNumber& c) {
if (c.getNBlocks()>blocks.size() || (c.getNBlocks()==blocks.size() and c.blocks[c.getNBlocks()-1]>blocks[getNBlocks()-1])) {
blocks.clear();
blocks.push_back(0);
} else {
for (unsigned int i(0); i<c.getNBlocks(); ++i) {
if (blocks[i]<c.blocks[i]) {
blocks[i+1] -= 1;
blocks[i] += limitBlock;
}
blocks[i]-=c.blocks[i];
}
}
Pop();
return *this;
}
BigNumber& operator*=(const unsigned int n) {
for (unsigned int i(0); i<blocks.size(); ++i) {
blocks[i]*=n;
}
Carry();
return *this;
}
BigNumber& operator/=(const unsigned int n) {
if (n==0) {
cout << "Cannot divide by 0!" << endl;
return *this;
}
for (int i(blocks.size()-1); i>=0; --i) {
if (i>0) {
blocks[i-1] += (blocks[i]%n) * limitBlock;
}
blocks[i] /= n;
}
Pop();
return *this;
}
};
const BigNumber operator+(BigNumber a, const BigNumber& b) {
a += b;
return a;
}
const BigNumber operator-(BigNumber a, const BigNumber& b) {
a -= b;
return a;
}
const BigNumber operator*(unsigned int a, const BigNumber& b) {
BigNumber c(b);
c *= a;
return c;
}
const BigNumber operator*(const BigNumber& b, const unsigned int a) {
BigNumber c(b);
c *= a;
return c;
}
const BigNumber operator/(const BigNumber& b, const unsigned int a) {
BigNumber c(b);
c /= a;
return c;
}
const BigNumber operator%(const BigNumber& b, const unsigned int a) {
BigNumber c(b);
c /= a;
c *= a;
return BigNumber(b - c);
}
ostream& operator<<(ostream&out, const BigNumber& n) {
n.print(out);
return out;
}
const BigNumber Fibonacci(unsigned int i);
int main(){
struct timeval start_time, end_time;
vector <BigNumber> Fib;
vector <BigNumber> duration;
cout << "Fibonacci Number : " << endl;
cout << "N:\tFibonacci(N)\tTime of estimation (us)"<< endl;
for (unsigned long i(0); i<=35; ++i) {
gettimeofday(&start_time,0);
BigNumber f = Fibonacci(i);
gettimeofday(&end_time,0);
duration.push_back(BigNumber(1000000*(end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec)));
Fib.push_back(f);
if (i>=2) {
cout << i << "\t"<< f << "\t" << duration[i]<< endl;
}
}
for (unsigned long i(36); i<=100; ++i) {
Fib.push_back(Fib[i-1]+Fib[i-2]);
duration.push_back(duration[i-1]+duration[i-2]);
cout << i << "\t"<< Fib[i] << "\t" << duration[i] << endl;
}
cout << endl;
cout << "Factorial" << endl;
BigNumber a(1);
for (unsigned int i(1); i<=100; ++i) {
a *= i;
cout << i<<"!= "<< a << endl;
}
return 0;
}
const BigNumber Fibonacci(unsigned int i) {
if (i==0) return BigNumber(0);
if (i==1) return BigNumber(1);
return Fibonacci(i-1)+Fibonacci(i-2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment