Skip to content

Instantly share code, notes, and snippets.

@ogregoire
Created October 17, 2015 18:49
Show Gist options
  • Save ogregoire/9da76e3451c41654e8f5 to your computer and use it in GitHub Desktop.
Save ogregoire/9da76e3451c41654e8f5 to your computer and use it in GitHub Desktop.
is perfect square
public class IsPerfectSquare {
// Taken from http://stackoverflow.com/a/18686659/180719
private static long goodMask = computeGoodMask(); // 0xC840C04048404040 computed below
private static long computeGoodMask() {
long goodMask = 0L;
for (int i = 0; i < 64; i++) {
goodMask |= Long.MIN_VALUE >>> (i * i);
}
return goodMask;
}
public static boolean isPerfectSquare(long x) {
// This tests if the 6 least significant bits are right.
// Moving the to be tested bit to the highest position saves us masking.
if (goodMask << x >= 0) {
return false;
}
final int numberOfTrailingZeros = Long.numberOfTrailingZeros(x);
// Each square ends with an even number of zeros.
if ((numberOfTrailingZeros & 1) != 0) {
return false;
}
x >>= numberOfTrailingZeros;
// Now x is either 0 or odd.
// In binary each odd square ends with 001.
// Postpone the sign test until now; handle zero in the branch.
if ((x & 7) != 1 || x <= 0) {
return x == 0;
}
// Do it in the classical way.
// The correctness is not trivial as the conversion from long to double is lossy!
final long tst = (long) Math.sqrt(x);
return tst * tst == x;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment