Hello. Such a problem, I conduct research to compare various methods of implementing the algorithm for calculating the Fibonacci number. But it turns out that in the 64-bit system the maximum number is 18446744073709551615. It is not enough for the 100th Fibonacci number - 218922995834555169026. How can I fit it? Of course, collecting an array of 100 string numbers will not work, you just need to calculate this number (218922995834555169026).

  • store numbers in two 64 bit variables. Or use 128 bit types. - KoVadim
  • KoVadim, Thank you. Here I would like to know how to use 128 bit types, I am very weak in C / C ++. - iproger
  • Use the gmp - avp library
  • Use long arithmetic . - αλεχολυτ

1 answer 1

Well, once again I will pull out my class from mothballs and use it to calculate Fibonacci numbers :)

#include <vector> #include <string> #include <iostream> #include <iomanip> using namespace std; class superLong { public: using ullong = unsigned long long; superLong(ullong x = 0) { d.push_back(x); }; superLong(string s); operator string() const; friend superLong operator *(const superLong&a, const superLong&b); friend superLong operator +(const superLong&a, const superLong&b); private: // Хранение чисел для простоты в виде кусков по 9 десятичных цифр vector<ullong> d; static constexpr ullong max = 1000000000ull; }; superLong operator *(const superLong&a, const superLong&b) { superLong r; for(size_t i = 0, e = adsize(); i < e; ++i) { for(size_t j = 0, f = bdsize(); j < f; ++j) { superLong::ullong v = ad[i]*bd[j]; superLong::ullong carry = v/superLong::max; v = v%superLong::max; if (i+j >= rdsize()) rdresize(i+j+1,0); rd[i+j] += v; if (carry) { if (i+j+1 >= rdsize()) rdresize(i+j+2,0); rd[i+j+1] += carry; } } } for(size_t i = 0, e = rdsize(); i < e-1; ++i) { if (rd[i] > superLong::max) { rd[i+1] += rd[i] / superLong::max; rd[i] %= superLong::max; } } return r; } superLong operator +(const superLong&a, const superLong&b) { superLong d((adsize() > bdsize()) ? a : b); superLong c((adsize() > bdsize()) ? b : a); cdresize(ddsize(),0); superLong::ullong carry = 0; for(size_t i = 0; i < ddsize(); ++i) { dd[i] += cd[i]+carry; carry = dd[i]/superLong::max; dd[i] %= superLong::max; } if (carry) ddpush_back(carry); return d; } superLong::superLong(string s) { superLong q; int len = s.length()%9; if (len) { string val = s.substr(0,len); s = s.substr(len,s.length()-len); q = stoll(val); } while (s.length()) { string val = s.substr(0,9); s = s.substr(9,s.length()-9); q = q * superLong::max + stoll(val); } d = std::move(qd); } superLong::operator string() const { string s; for(size_t i = 0; i < d.size(); ++i) { char buf[12]; snprintf(buf,12,"%09lld",d[i]); s = buf + s; } int i = 0; while(s[i] == '0') ++i; if (s[i] == 0) --i; return s.substr(i); } superLong superPow(superLong x, unsigned long long p) { superLong r(1); while(p) { if (p&0x01) r = r * x; p >>= 1; x = x*x; } return r; } int main(int argc, const char * argv[]) { superLong f0(1); superLong f1(1); for(int i = 3; i < 100; ++i) { superLong f = f0 + f1; f0 = f1; f1 = f; } cout << string(f1) << endl<<endl;; } 
  • Wow, thank you so much!) Powerful class. Compare with gmp necessarily - iproger
  • Well, if you like it, accept the answer as satisfactory :) - Harry
  • Yes, of course, I just got carried away and completely forgot!) Thank you so much!) - iproger
  • Compare not worth it. The answer will be the same, but this class does not shine with either efficiency or universality. He wrote in response to a question about long arithmetic, purely as a demonstration of the principle. - Harry
  • Yes, this is a very good answer, I wonder how it works inside and here you can see everything. We probably have fewer c ++ people on the forum, we should have already put a lot of advantages in it) to compare the time of the methods is interesting. Perhaps yours will be even faster, or about the same, as I suppose similar principles are used. - iproger