4

UPDATE:

Thank you for the helpful comments and advice. Using what you guys said, this is what I've come up with:

#include <limits.h>
  ...
  else {
     int a = binom(n - 1, k - 1);
     int b = binom(n - 1, k);
     if(a > 0) {
         if (b > INT_MAX - a) {          // case 1: integer overflow
             printf("int overflow\n");
             return;
         }
     }
     else if (b < INT_MIN - a) {         // case 2: integer overflow
         printf("int overflow\n");
         return;
     }
     int c = a + b;
     return c;
}

I do have another question. In the above code, when I catch the integer overflow I am not returning a value -- it is simply return;.

One of the comments below suggested return -1;, however this wouldn't work work considering -1 is still a valid integer, correct?

I am not sure what to do since the return type is int for my function. Does return; work or is there a better way to do it? Also suggested was exit(1);, but does that exit the entire program or just the function?


ORIGINAL:

Your function should use integer arithmetic to make sure that the results are exact and also detect any integer overflows caused by exceeding the maximum allowed values.

I am trying to catch an integer overflow when computing binomial coefficients. While a simple concept, what is throwing me off is that this isn't just a one-off addition, it's a recursive algorithm that is constantly performing sums.

This is the function:

// recursive function to calculate binomial coefficients
int binom(int n, int k){
    if(k == 0){         // base case
         return 1;
    }
    else if (n == 0){
         return 0;
    }
    else{
         return binom(n - 1, k - 1) + binom(n - 1, k);  // recursive call

    }
}

Under that logic, I assume the catch should be in the recursive call statement. Something like :

if(binom(n-1, k-1) + binom(n-1,k)) causes overflow, return error, else proceed with binom(n-1, k-1) + binom(n-1,k)

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Milan Patel
  • 53
  • 1
  • 1
  • 5

3 Answers3

3

Signed overflow are undefined behavior you have to check the overflow before it can happen.

int a, b;
int c;

...

/* Compute a + b and store the result in c */

if (a > 0) {
    if (b > INT_MAX - a) {
        // a + b overflows (i.e., would be > INT_MAX)
    }
} else if (b < INT_MIN - a) {
        // a + b overflows (i.e., would be < INT_MIN)
}

c = a + b;

so for a recursive function:

a = binom(n - 1, k - 1);
b = binom(n - 1, k);

// if no overflow
c = a + b;

return c;

In your example, you also have to check n and k are not == INT_MIN otherwise the - 1 operation will also overflow.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • Many thanks -- this is the implementation I went with. I did have one other question. How would I break out of the function if there is an overflow? If I return a integer flag like -1 (as suggested below), since this is recursive it will continue to sum as -1 is a number. – Milan Patel Feb 27 '12 at 18:59
0

Do something like:

long res=(long)binom(n - 1, k - 1) + binom(n - 1, k);
if (res>INT_MAX) {
 printf("int overflow\n");
 exit(1);
}
return (int)res;

(Assuming that long is longer than int in your system. If not so, use wider type)

Edit: if you don't want to exit at error, you should decide a value (for example, -1), to represent error. also, it's nicer (and correcter) you use unsigned instead of long:

int a=binom(n - 1, k - 1),b=binom(n - 1, k);
if (a<0 || b<0 || (unsigned)a+(unsigned)b>INT_MAX) return -1;
return a+b;
asaelr
  • 5,438
  • 1
  • 16
  • 22
0

A few suggestions:

1) You're using a signed integer; if you're working with strictly positive quantities, you should probably use an unsigned int or unsigned long long. With a signed int, when an arithmetic overflow occurs it'll overflow to the largest negative number possible

2) The compiler will define a pre-processor symbol along the lines of INT_MAX; you can probably make good use of it, eg something like this:

#inlcude <stdtypes.h>

uint32_t binom( uint32_t n, uint32_t k ){
  // (...)
  } else {
    int32_t   A = binom( n-1, k-1 )
            , B = binom( n-1, k );
    if( (double)A + (double)B > INT_MAX ){
      // error condition
    } else {
      retval = A+B;
    }
  }

  return retval;
}
Brian Vandenberg
  • 4,011
  • 2
  • 37
  • 53