# Thread: Checking for integer after square root

1. ## Checking for integer after square root

Hi,
its seems like a simple problem but i can't seem to find any simple C/C++ tools to help me with what i'm looking for...

I have a long variable, I wanna take the square root of that long variable and then I want to check if the result of the square root is an integer (has no decimal values).

any thoughts?

Boomba,

2. Code:
```int i = some_positive_value();
double x = sqrt((double)i);
int root_i = (int)x;
if (root_i *root_i == i) square_root_is_integer();```
If you want to do away with working with floating point values (which also introduces some potential for rounding errors to mess things up), you need to use a loop;
Code:
```/*  assume i is > 0 */
int root_i = 0;
while (root_i * root_i < i)  ++root_i;
/*   root_i will be an integer that is not less than the square root of i */
if (root_i * root_i == i) square_root_is_integer();```

3. Here is a simple method:
Code:
```/*root be the variable containing square root*/
Check for this condition:

if(root-(int)root==0)
...it is an integer value
else
...it is not```

4. No, logicwonder's method is unsafe, because floating points are imprecise. grumpy got it right.

Code:
```#include <iostream>
#include <cmath>
using namespace std;

int main ( )
{
double d = 256.2;
double s = sqrt ( d );

int x = ( int ) s ;

if ( fmod ( s, ( int ) s ) == 0 )
{
cout << "Integer!";
}
return 0;
}```
- Micko

6. It might work (not sure what exactly fmod does), but what for? Grumpy's version is fine, simple, and nearly guaranteed to work. To make it safe, the integer conversion line must be modified like so:
Code:
`int root_i = (int)(x + 0.5);`
Otherwise, x might be just below the actual integer value, and the resulting downrounding makes it incorrect.

7. Originally Posted by CornedBee
It might work (not sure what exactly fmod does), but what for? Grumpy's version is fine, simple, and nearly guaranteed to work. To make it safe, the integer conversion line must be modified like so:
Code:
`int root_i = (int)(x + 0.5);`
Otherwise, x might be just below the actual integer value, and the resulting downrounding makes it incorrect.
Ok, Grumpy's solution is fine.
I'm not sure why you need to do this:
Code:
`int root_i = (int)(x + 0.5);`
I didn't quite understand...
You have floor and ceil functions from cmath but don't know in which case ...+0.5 is needed...

8. Floating point numbers are imprecise, and square root algorithms only deliver approximations. It is well possible that, say, sqrt(1000000.0) doesn't return exactly 1000.0, but, say, 1000.0001 or perhaps 999.9999. The first is not a problem, because converting it to an integer will still yield 1000. However, integer conversion always rounds toward zero, no matter how small the difference is; thus, 999.9999 will yield 999 when converted to an integer. 999*999 is not 1000000, so the test will incorrectly fail. Adding 0.5 to the result ensures that the result will be correct either way. (The error will not go beyond 0.5 until the numbers become very large - probably too large for an integer anyway.)

9. A less elegant, yet highly precise solution would have you simply convert the resultant value to a string and analyze that.

Code:
```bool is_sqrt_int(double your_value) {
std::ostringstream ostr;
ostr << square_root_of(your_value);
return ostr.str().find(".") == std::string::npos;
}```

As far as calculating the square root is concerned, I prefer Newton's iteration:
Code:
```result = 1

for i = 1 to N
result = (result + (value / result)) / 2```
where N is the number of iterations you'd like. (The more iterations, the more precise the value, but I find just a few to be enough. Experiment yourself.)
[/edit]

10. Except if the global locale was replaced by a German one, which would cause the stream to output 123.456 as "123,456".

11. Originally Posted by CornedBee
Except if the global locale was replaced by a German one, which would cause the stream to output 123.456 as "123,456".
Search the string for the current locale's integer and decimal separator. (You're splitting hairs, CornedBeef. In a real situation that might present a serious concern, but our friend is surely authoring a small program where he knows what his decimal character is.)

Of course, you could always simply check the string for a non-numeric, non-sign character.
Code:
`return ostr.str().find_first_not_of("-+0123456789") == std::string::npos;`
[/edit]

12. I use this all the time:

Code:
```bool is_int(double value)
{
if ( (value / static_cast<int>(value)) == 1) return true;
else return false;

}```
I have never come across any rounding errors with it, but I suppose it is possible. It is just simple and worked for everything I needed it with.

13. Originally Posted by CornedBee
No, logicwonder's method is unsafe, because floating points are imprecise. grumpy got it right.
No, logicwonder's method is just as safe as grumpy's. Grumpy uses floating point numbers, too. (Both will work correctly; a double can hold unsigned integers exactly up to about 52 bits.)

Originally Posted by CornedBee
It is well possible that, say, sqrt(1000000.0) doesn't return exactly 1000.0, but, say, 1000.0001 or perhaps 999.9999.
If you're using a 32-bit or 64-bit IEEE representation, this will only happen if the square root implementation is broken. If you're paranoid about broken implementations, then rounding works, though.

If you increase your number to, say, 32 million, then you'll get problems. You end up getting false positives, not false negatives.

14. Originally Posted by Rashakil Fol
No, logicwonder's method is just as safe as grumpy's. Grumpy uses floating point numbers, too. (Both will work correctly;
Actually, I provided two methods. One of them used floating point variables, and is just as safe (or unsafe) as logicwonder's method. The other method used purely integer arithmetic, and does not have the potential for errors due to lack of precision in floating point.
Originally Posted by Rashakil Fol
a double can hold unsigned integers exactly up to about 52 bits.)
That's not required to be true. It just happens to be true for some common floating point representations.