Reputation: 9
In C/C++:
I need to find if some big numbers are perfect squares, but my code finds numbers like 851659987045856130 to be valid, when 922854261.00000000487617621781778 is the actual square root(to a larger precision) and is not an integer. Is there any way to delay the rounding for a better precision? I know that the number above doesn't even have "perfect square last digit(s)", but I want to know in general if it is possible to check if such a big number is in fact a perfect square with a reasonable but higher precision than standard.
Upvotes: 0
Views: 524
Reputation: 126787
It's not just like std::sqrt
is not precise enough, it's that double
s aren't even precise enough to represent your input correctly. To have a valid result, you have to perform your "real" check in integer arithmetic.
A simplistic alternative to the integer square root method can be to use the result of std::sqrt
as a hint for an exact search of the square:
bool is_square(int64_t val) {
int64_t guess = std::sqrt(val);
for(int64_t g=guess;;++g) {
if(g*g==val) return true;
if(g*g>val) break;
}
for(int64_t g=guess-1;;--g) {
if(g*g==val) return true;
if(g*g<val) break;
}
return false;
}
I suspect that this may be faster than the "real thing" in most cases, given that the floating point square root algorithm may even be implemented in hardware and thus should give the starting point really quickly (the rest of the algorithm should be extremely fast, both loops should exit after a handful of iterations).
Upvotes: 1
Reputation:
The best thing to do here is to use an exact square root algorithm. If that number is representative of the size you're testing, you wouldn't even need a multiprecision arithmetic package — however, such a package would be the easiest place to obtain an implementation of such an algorithm. In fact, it would probably implement is_square
directly (and might be faster than by computing a square root).
If you were curious about rolling your own implementation, the usual approach is Newton's method; e.g. as seen at https://en.wikipedia.org/wiki/Integer_square_root .
Upvotes: 1
Reputation: 1294
Truncate the result to int, then multiply it by itself to see if you end up with the original number.
Upvotes: -1