Negar Nasiri
Negar Nasiri

Reputation: 466

best way to recognize and handle integer overflow in c?

I am so new in C and so far I didn't comprehend how to prevent from integer overflow, I read many articles but still I am not 100% sure! in this case

int ft_sqrt(int nb)
{
    long int    sqrt;
    
    if (nb <= 0)
        return (0);
    if (nb == 1)
        return (1); 
    sqrt = 1;
    while (sqrt * sqrt < nb)
    {
        sqrt++;
    }
    if (sqrt * sqrt == nb)
        return (sqrt);
    else
        return (0);
}

to prevent overflow should I use

long

? what is the best practice to do that?

Upvotes: 2

Views: 196

Answers (2)

So, first of all, you need to know if you want to detect an overflow or if you could just avoid them.

To just avoid them, if you know how long nb can be, maybe you could see if long or long long is big enough. And, if it isn't, maybe the solution proposed by @Jonathan Leffler of using while (sqrt < nb / sqrt) is the way to making it fit in one of those types.

Now, if you really want/need to check for overflow, then you'll need to check for square_root(MAX_NUMBER_ALLOWED) < sqrt, where MAX_NUMBER_ALLOWED would depend on which type you are using. C/C++ already have constants for that, you can check them here.

Upvotes: 2

chux
chux

Reputation: 154174

long is not certainly wider than int and so its use may not widen the computation.


To certainly avoid overflow, don't multiple, but divide.

int ft_sqrt(int nb) {
    int    sqrt;
    if (nb <= 0)
        return (0);
    if (nb == 1)
        return (1); 
    sqrt = 1;
    // while (sqrt * sqrt < nb)
    while (sqrt < nb / sqrt) {
        sqrt++;
    }
    if (sqrt == nb / sqrt)
        return (sqrt);
    else
        return (0);
}

Yes code takes a performance hit - yet OP algorithm has many ways for improvement)


Alternate code:

unsigned bit_width(unsigned x) {
  unsigned width = 0;
  while (x) {
    x /= 2;
    width++;
  }
  return width;
}

unsigned usqrt(unsigned x) {
  if (x == 0) {
    return 0;
  }
  unsigned y = 1u << bit_width(x) / 2;
  unsigned y_previous;
  unsigned diff;
  unsigned diff1count = 0;

  do {
    y_previous = y;
    y = (y + x / y) / 2;
    diff = y_previous < y ? y - y_previous : y_previous - y;
    if (diff == 1)
      diff1count++;
  } while (diff > 1 || (diff == 1 && diff1count <= 1));
  y = (y_previous + y) / 2;
  return y;
}

Upvotes: 1

Related Questions