Catching an Integer Overflow in a recursive function [C]

Refresh

December 2018

Views

377 time

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)

3 answers

3

Подпись переполнение не определенно поведение, вы должны проверить переполнение прежде, чем это может случиться.

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;

так что для рекурсивной функции:

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

// if no overflow
c = a + b;

return c;

В вашем примере, вы должны также проверить nи kне == INT_MINиначе - 1операция будет также переполнение.

0

Несколько предложений:

1) Вы используете целое число; если вы работаете со строго положительными величинами, вы, вероятно, следует использовать неподписанных Int или без знака долго долго. С подписанным междунар, когда происходит арифметическое переполнение она будет переливаться к наибольшему отрицательному числу возможного

2) Компилятор будет определить символ предварительно процессора вдоль линий INT_MAX; Вы, вероятно, может хорошо использовать его, например, что-то вроде этого:

#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;
}
0

Сделайте что-то вроде:

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;

(Если предположить , что longбольше , чем intв вашей системе. Если не так, шире использовать тип)

Edit: если вы не хотите , чтобы exitна ошибки, вы должны решить , значение (например, -1), для представления ошибки. Кроме того , это лучше (и correcter) вы используете unsignedвместо 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;