Reputation: 466
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
Reputation: 21
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
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