Created
October 17, 2015 18:49
-
-
Save ogregoire/9da76e3451c41654e8f5 to your computer and use it in GitHub Desktop.
is perfect square
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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