Overflow while calculating combinations - c++

I am trying to calculate the combination C(40, 20) in C++, however the data types in C++ seems unable to correctly handle this calculation even though I have used long long data type. The following is my code:
#include <iostream>
long long fac(int x) {
register long long i,f = 1; // Optimize with regFunction
for(i = 1;i <= x;i++)
f *= i;
std::cout << f << std::endl;
return f;
}
// C(n,r) = n!/r!(n-r)!
long long C(long long n, long long r) {
return fac(n) / (fac(r) * fac(n - r));
}
int main(int argc, char const *argv[]) {
std::cout << C(40, 20) << std::endl;
return 0;
}
Any idea to solve this problem?

Compute C at once by executing division immediately after multiplication:
long long C(long long n, long long r)
{
long long f = 1; // Optimize with regFunction
for(auto i = 0; i < r;i++)
f = (f * (n - i)) / (i + 1);
return f ;
}
Result should be exact (divisions without remainders, until overflows) since any integer factor present in (i+1) is already present in (n -i). (Should not be too difficult to prove)

Your numbers are growing too much and that is a common problem in this kind of calculations and I am afraid there is no straightforward solution. Even if you might reduce a bit the number of multiplications you will make probably still you will end up in an overflow with long long
You might want to check those out:
https://mattmccutchen.net/bigint/
https://gmplib.org/
I know there are different algorithmic approaches on this matter. I remember there were some solutions to use strings to store integer representations and stuff but as #Konrad mentioned this might be a poor approach to the matter.

The problem is that factorials get big very quickly. 40! is too large to be stored in a long long. Luckily you don’t actually need to compute this number here since you can reduce the fraction in the calculation of C(n, r) before computing it. This yields the equation (from Wikipedia):
This works much better since k! (r! in your code) is a much smaller number than n!. However, at some point it will also break down.
Alternatively, you can also use the recurrence definition by implementing a recursive algorithm. However, this will be very inefficient (exponential running time) unless you memoise intermediate results.

A lazy way out would be to use a library that supports multiple precision, for example GNU GMP.
Once you have installed it correctly (available from the repositories on most Linux distributions), it comes down to:
adding #include <gmpxx.h> to your source file
replacing long long with mpz_class
compiling with -lgmpxx -lgmp
The source:
#include <iostream>
#include <gmpxx.h>
mpz_class fac(mpz_class x) {
int i;
mpz_class f(1); // Optimize with regFunction
for(i = 1;i <= x;i++)
f *= i;
std::cout << f << std::endl;
return f;
}
// C(n,r) = n!/r!(n-r)!
mpz_class C(mpz_class n, mpz_class r) {
return fac(n) / (fac(r) * fac(n - r));
}
int main(int argc, char const *argv[]) {
std::cout << C(40, 20) << std::endl;
return 0;
}
Compiling and running:
$ g++ comb.cpp -lgmpxx -lgmp -o comb
$ ./comb
2432902008176640000
2432902008176640000
815915283247897734345611269596115894272000000000
137846528820
If you want to be thorough, you can do a lot more, but this will get you answers.

Even if you used uint64 aka ulonglong, the max value is 18446744073709551615 whereas 40! is 815915283247897734345611269596115894272000000000 which is a bit bigger.
I recommend you to use GMP for this kind of maths

Related

Problem when i used some large large value i get wrong output with my function

So I'm new to stackoverflow and coding I was learning about functions in c++ and how the stack frame works etc..
in that I made a function for factorials and used that to calculate binomial coefficients. it worked fine for small values like n=10 and r=5 etc... but for large a medium value like 23C12 it gave 4 as answer.
IDK what is wrong with the code or I forgot to add something.
My code:
#include <iostream>
using namespace std;
int fact(int n)
{
int a = 1;
for (int i = 1; i <= n; i++)
{
a *= i;
}
return a;
}
int main()
{
int n, r;
cin >> n >> r;
if (n >= r)
{
int coeff = fact(n) / (fact(n - r) * fact(r));
cout << coeff << endl;
}
else
{
cout << "please enter valid values. i.e n>=r." << endl;
}
return 0;
}
Thanks for your help!
You're not doing anything "wrong" per se. It's just that factorials quicky become huge numbers.
In your example you're using ints, which are typically 32-bit variables. If you take a look at a table of factorials, you'll note that log2(13!) = 32.535.... So the largest factorial that will fit in a 32-bit number is 12!. For a 64-bit variable, the largest factorial you can store is 20! (since log2(21!) = 65.469...).
When you get 4 as the result that's because of overflow.
If you need to be able to calculate such huge numbers, I suggest a bignum library such as GMP.
Factorials overflow easily. In practice you rarely need bare factorials, but they almost always appear in fractions. In your case:
int coeff = fact(n) / (fact(n - r) * fact(r));
Note the the first min(n,n-r,r) factors of the denominator and numerator are identical. I am not going to provide you the code, but I hope an example will help to understand what to do instead.
Consider n=5, r=3 then coeff is
5*4*3*2*1 / 2*1 * 3*2*1
And before actually carrying out any calculations you can reduce that to
5*4 / 2*1
If you are certain that the final result coeff does fit in an int, you can also calculate it using ints. You just need to take care not to overflow the intermediate terms.

C++ pow() function changes behaviour when put inside a function

I have been programming in C++ for a while now. I have seen previously that power function gives wrong answer for bigger powers due to precision issues but today while solving coding problems I saw that under the same type of parameters, pow() function gave different values when put inside a function vs when evaluated directly.
#include <iostream>
#include <math.h>
using namespace std;
long long n,d;
long long power(long long x)
{
return pow(100,x);
}
long long powersecond(long long x)
{
return pow(100,(int)x);
}
int main()
{
n = 68; d = 2;
cout << n*power(d) <<endl; // outputs 679932
cout << n*pow(100,d) <<endl; // outputs 680000
cout << n*powersecond(d) <<endl; // outputs 679932
cout << n*pow(100,(int)d) <<endl; // outputs 680000
return 0;
}
Notice that the answer doesn't change even after converting x to integer in powersecond() function.The answer is still 679932 even if d is int instead of long long int.
The compiler I used is gnu gcc compiler in VS Code.
The problem is that the output of pow is a floating point double. In your custom function you convert that output to long long, which will truncate if the value returned by pow is slightly low instead of slightly high. See Is floating point math broken?. When you call pow directly the value is kept as a double even after the multiplication, and output rounding gives you a more accurate result.
You expect the value returned by pow(100,2) to be 10000, but instead it might be 9999.99999999999 because of the way floating point works. When converted to integer, that becomes 9999; multiplied by 68, you have 679932.
On the other hand, 9999.99999999999 multiplied by 68 becomes 679999.999999999. That's close enough to 680000 that the output function << will round it for you. You can get a more exact figure if you apply output formatting.
Always write your own power function whenever needed. Change return type according to your requirement to avoid any kind of confusion.
long long int power(long long int a, long long int x) {
static long long int ans = 1;
if (x < 0)
return 1 / power(a, (-1 * x));
if (x == 1)
return a;
if (x == 0 or a == 1)
return 1;
if (x & 1)
ans = a * power((a * a), x / 2);
else
ans = power((a * a), x / 2);
return ans;
}
Here is recursive version .You can also write iterative version.

C++ function to calculate factorial returns negative value

I've written a C++ function to calculate factorial and used it to calculate 22C11 (Combination). I have declared a variable ans and set it to 0. I tried to calculate
22C11 = fact(2*n)/(fact(n)*fact(n))
where i sent n as 11. For some reason, i'm getting a negative value stored in answer. How can i fix this?
long int fact(long int n) {
if(n==1||n==0)
return 1;
long int x=1;
if(n>1)
x=n*fact(n-1);
return x;
}
The following lines are included in the main function:
long int ans=0;
ans=ans+(fact(2*n)/(fact(n)*fact(n)));
cout<<ans;
The answer i'm getting is -784
The correct answer should be 705432
NOTE: This function is working perfectly fine for n<=10. I have tried long long int instead of long int but it still isn't working.
It is unwise to actually calculate factorials - they grow extremely fast. Generally, with combinatorial formulae it's a good idea to look for a way to re-order operations to keep intermediate results somewhat constrained.
For example, let's look at (2*n)!/(n!*n!). It can be rewritten as ((n+1)*(n+2)*...*(2*n)) / (1*2*...*n) == (n+1)/1 * (n+2)/2 * (n+3)/3 ... * (2*n)/n. By interleaving multiplication and division, the rate of growth of intermediate result is reduced.
So, something like this:
int f(int n) {
int ret = 1;
for (int i = 1; i <= n; ++i) {
ret *= (n + i);
ret /= i;
}
return ret;
}
Demo
22! = 1,124,000,727,777,607,680,000
264 = 18,446,744,073,709,551,615
So unless you have 128-bit integers for unsigned long long you have integer overflow.
You are triggering integer overflow, which causes undefined behaviour. You could in fact use long long int, or unsigned long long int to get a little bit more precision, e.g:
unsigned long long fact(int n)
{
if(n < 2)
return 1;
return fact(n-1) * n;
}
You say you tried this and it didn't work but I'm guessing you forgot to also update the type of x or something. (In my version I removed x as it is redundant). And/or your calculation still was so big that it overflowed unsigned long long int.
You may be interested in this thread which shows an algorithm for working out nCr that doesn't require so much intermediate storage.
You increasing your chances of success by avoiding the brute force method.
COMB(N1, N2) = FACT(N1)/(FACT(N1-N2)*FACT(N2))
You can take advantage of the fact that both the nominator and the denominator have a lot of common terms.
COMB(N1, N2) = (N1-N2+1)*(N1-N2+2)*...*N1/FACT(N1)
Here's an implementation that makes use of that knowledge and computes COMB(22,11) with much less risk of integer overflow.
unsigned long long comb(int n1, int n2)
{
unsigned long long res = 1;
for (int i = (n1-n2)+1; i<= n1; ++i )
{
res *= i;
}
for (int i = 2; i<= n2; ++i )
{
res /= i;
}
return res;
}

What is wrong with this recursive factorial implementation?

I compiled and run in my computer, and it executes correctly. I tried IDEONE, and I got a successful answer.
But when I submit it in SPOJ, I'm getting a wrong answer. Is something wrong in this implementation?
#include <iostream>
#include <cstdio>
using namespace std;
int factorial(int n) {
if (n <= 1)
return 1;
return n * factorial(n - 1);
}
int main() {
int t;
int n;
cout << "";
cin >> t;
for (int i = 0; i < t; i++) {
cout << "";
cin >> n;
printf("%d\n", factorial(n));
}
return 0;
}
The problem with the above code is due to the finite space we can use to store the value of an int. On a 32-bit machine, int's have 32 bits (value 0 or 1), which means that the maximum value an unsigned int can have is (2^31 - 1) and the maximum value an int can have is (2^30 - 1) (since it needs one bit to denote whether it is positive or negative, while the unsigned int is always positive and can devote that bit to just regular value).
Now, that aside, you should look into ways of storing the value of a very large number in a different data structure! Maybe an array would be a good choice...
Just to brainstorm, imagine creating an int bigInteger[100] (that should be large enough to hold 100!). To multiply two of your numbers, you could then implement a bitMultiplication(int bitNum[], int num) function that would take in your array by reference and perform bitwise multiplication (see the following post for details: Multiplying using Bitwise Operators).
Use that bitMulitiplication(int bitNum[], int num) instead of the regular multiplication in your recursive factorial function, and you should have a function that works on large n!

GCD function in c++ sans cmath library

I'm writing a mixed numeral class and need a quick and easy 'greatest common divisor' function. Can anyone give me the code or a link to the code?
The libstdc++ algorithm library has a hidden gcd function (I'm using g++ 4.6.3).
#include <iostream>
#include <algorithm>
int main()
{
std::cout << std::__gcd(100,24); // print 4
return 0;
}
You are welcome :)
UPDATE: As #chema989 noted it, in C++17 there is std::gcd() function available with <numeric> header.
I'm tempted to vote to close -- it seems difficult to believe that an implementation would be hard to find, but who knows for sure.
template <typename Number>
Number GCD(Number u, Number v) {
while (v != 0) {
Number r = u % v;
u = v;
v = r;
}
return u;
}
In C++ 17 or newer, you can just #include <numeric>, and use std::gcd (and if you care about the gcd, chances are pretty fair that you'll be interested in the std::lcm that was added as well).
A quick recursive version:
unsigned int gcd (unsigned int n1, unsigned int n2) {
return (n2 == 0) ? n1 : gcd (n2, n1 % n2);
}
or the equivalent iterative version if you're violently opposed to recursion (a):
unsigned int gcd (unsigned int n1, unsigned int n2) {
unsigned int tmp;
while (n2 != 0) {
tmp = n1;
n1 = n2;
n2 = tmp % n2;
}
return n1;
}
Just substitute in your own data type, zero comparison, assignment and modulus method (if you're using some non-basic type like a bignum class, for example).
This function actually came from an earlier answer of mine for working out integral aspect ratios for screen sizes but the original source was the Euclidean algorithm I learnt a long time ago, detailed here on Wikipedia if you want to know the math behind it.
(a) The problem with some recursive solutions is that they approach the answer so slowly you tend to run out of stack space before you get there, such as with the very badly thought out (pseudo-code):
def sum (a:unsigned, b:unsigned):
if b == 0: return a
return sum (a + 1, b - 1)
You'll find that very expensive on something like sum (1, 1000000000) as you (try to) use up a billion or so stack frames. The ideal use case for recursion is something like a binary search where you reduce the solution space by half for each iteration. The greatest common divisor is also one where the solution space reduces rapidly so fears about massive stack use are unfounded there.
For C++17 you can use std::gcd defined in header <numeric>:
auto res = std::gcd(10, 20);
The Euclidean algorithm is quite easy to write in C.
int gcd(int a, int b) {
while (b != 0) {
int t = b;
b = a % b;
a = t;
}
return a;
}