so I came across a problem,the problem is quite common.When getting the factorial of a number such as 50 or a 100 even a unsigned long long will not be big enough to store the result,
so I turned to GMP but I have a few questions regarding it the first one is with the base in the set_str() function
after reading this I cannot determine what base would be used for decimal or base 10,the obvious choice would be 10 right?
second what is meant by : For bases up to 36, case is ignored; upper-case and lower-case letters have the same value. For bases 37 to 62, upper-case letter represent the usual 10..35 while lower-case letter represent 36..61.
and moving on from bases,how o I actually store a very very large number a number greater than 20 digits using GMP?
from what I can see is you have to assign it in the form of a string why is this(I'm guessing it's because c++ won't support numbers greater than 19 digits?)
secondly how do I actually add these numbers/strings and use them in computations?
from what I read it seems that GMP is a nightmare to get setup,but it took me less than a minute all I did was download a compressed file,extracted it put the header file in my mingw's include directory and also put the lib file in the lib folder of mingw,I then statically linked to the GMP lib file and all seems to be running fine giving me the expected outputs,so I'm hoping I didn't install it wrong.
but why are some people saying you need CYGWIN and or need to make/build it to get it running?
If a base is more than 10, then letters are used for the higher digits: A is 10, B is 11, ..., Z is 35. If the base is less than 37 then lowercase letters are the same as uppercase letters: a=10, b=11, etc. If the base is over 36 (so that digits over 35 are needed) then the lowercase letters stand for the higher values: a is 36, b is 37, ..., z is 61
Yes, a string is used for input since C++ can't handle numbers larger than a certain size. Also, you may need to enter high-base values like MX3T2V, which make no sense at all in C++.
I have no idea why anyone would say it's a "nightmare" to set up.
With C++ it's probably best to use boost multiprecision. You can use GMP as a backend, if you want. You can also use the "header only" version (but using GMP as a backend is more efficient):
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
typedef mp::number<mp::cpp_int_backend<2048,2048,mp::signed_magnitude,mp::unchecked,void>> int2048_t;
int main() {
// Pre-defined sizes only for 128, 256, 512, and 1024 bits.
mp::int128_t i128;
mp::int256_t i256;
mp::int512_t a("33333333333333333333"); // value is beyond 64-bits
mp::int1024_t b( 5555555555555555555 );
// But you can make your own size.
int2048_t c;
// Math is done normally (due to operator overloading in C++)
c = a * b;
std::cout << c << '\n'; // 185185185185185185164814814814814814815
}
cygwin is useful for code that has a hefty amount of unix OS specific junk in it to get it to work on windows. Most of the time you can just remove unistd.h and poke a couple of things and get it working on windows, but when you can't, cygwin is one choice (of several) to build a lib file that you can use on windows without too much trouble. Cygwin also lets you run c++ programs that have unix system calls embedded in them, eg system("grep") type utility programs. I don't see ANY reason for that here. Maybe an older version of the software had unixisms in it that were a pain to compile on windows.
(I'm guessing it's because c++ won't support numbers greater than 19 digits?)
Try not to think this way :) C++ does not care about the size of atomic data, and the day where we all have 128 bit registers is not long off, and the FPU on most machines supports at least 80 bits, some 100 or so bits, I forget the current exact sizes, and you can USE those in c++ with some hand waving. The purpose of the extra bits in the FPU is to protect you from round-off, so if you use the full measure, you lose this protection -- you were warned. But for simple things like factorial you can squeeze a few more values out of the extended ranges if you want to do so. How to access the extended data varies... some compilers have extended types to support them, some you have to define your own and use a line or two of assembler to get at it. The limitation isnt the language --- it is the compiler and current hardware norms. If every cpu had a 128 bit register next year, g++ could make 'int' or 'unsigned long long' 128 bits instead of 64 and your code would deal with it just fine. PRINTING the extended values, if not supported, is going to be annoying. If you want more than the hardware can give, the software extension libraries will do it, but use the hardware as far as you can push it if you want performance. The software libs are going to be slower. Given how few factorials you probably want using the software before pushing the hardware is fine. No one wants billions of factorials, but if you need to store billions of extended doubles, the hardware is worth talking about.