Sunday, October 19, 2014

Handling big numbers in C programming language


Hello everyone,



If you are coding in the C programming language and need to work with some really big numbers then, you will normally hit an impasse. This is so because in most machines, a long long int is 8 bytes (I am using gcc 4.7.2-5 on a Linux x86_64 machine).
This means that you can't find the factorial of a number say 34. What if you want to find the "Central binomial coefficient" of n, where n=34. 



In such cases, you can get around this problem by downloading GMP (GNU Multiple Precision arithmetic library) from "https://gmplib.org/" and installing it on your machines. 
After you have successfully installed gmp on your machine, you can compile your programs using "gmp" by giving the following command in your *nix like machines:

$ gcc <name_of_program>.c -lgmp


And if everything was done/coded properly, hopefully you will get the "a.out" file (if you haven't given the "-o" option to gcc to rename the binary)




This is a very brief tutorial to get you jump started on how to use
gmp:

/* A program to calculate the central binomial coefficient for n

central binomial coefficient =
{2n \choose n} = \frac{(2n)!}{(n!)^2}\text{ for all }n \geq 0.
*/

#include<stdio.h>
#include<gmp.h>  // you have to include this header file in your source code


int main()
{
    mpz_t num, denom, final;  // to use an int, use mpz_t
    int n, m = 1;

    mpz_init(num);  // it is imperative to initialize an mpz_t variable before you intend to use it
    mpz_init(denom);
    mpz_init(final);   

    printf("Enter n: ");
    scanf("%uld", &n);
    m = 2*n;


    mpz_set_ui(num, 1);     // set num to 1. ui means unsigned long int
    mpz_set_ui(denom, 1);
    mpz_set_ui(final, 1);
    mpz_init_set_str(two, "2", 10);  // to combine initialization and assignment in a line

    // DO NOT use an initiliaze and set function on a variable already initialized

 

    mpz_fac_ui(num, m); // set num to factorial of n. n has to be unsigned long int
    mpz_fac_ui(denom, n);
   
 

    mpz_mul(denom, denom, denom); // denom = denom * denom
   
    mpz_cdiv_q(final, num, denom); // final = nu, / denom

    gmp_printf("num: %Zd\n", num);  // to print, use gmp_printf()
    gmp_printf("denom: %Zd\n", denom);
    gmp_printf("Division result: %Zd\n\n", final);

    mpz_clear(num);  // clear the mpz_t variables after you are done with them
    mpz_clear(denom);
    mpz_clear(final);
  


return 0;
}



I hope that you find this little tutorial interesting as it gives the C programmers an alternative to handle large precision numbers.


I am well aware that using other languages say like Python, can achieve the same result more efficiently in lesser number of lines of codes. But, the optimization in terms of execution speed that can be done using C as opposed to Python is something that can prove as a tipping point to start using gmp!