Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a good algorithm to determine if an input is a perfect square? [duplicate]

Possible Duplicate:
Fastest way to determine if an integer's square root is an integer

What's a way to see if a number is a perfect square?

bool IsPerfectSquare(long input) {    // TODO } 

I'm using C# but this is language agnostic.

Bonus points for clarity and simplicity (this isn't meant to be code-golf).


Edit: This got much more complex than I expected! It turns out the problems with double precision manifest themselves a couple ways. First, Math.Sqrt takes a double which can't precisely hold a long (thanks Jon).

Second, a double's precision will lose small values ( .000...00001) when you have a huge, near perfect square. e.g., my implementation failed this test for Math.Pow(10,18)+1 (mine reported true).

like image 701
Michael Haren Avatar asked Dec 05 '08 13:12

Michael Haren


People also ask

How do you quickly check if a number is a perfect square?

To check the perfectness of your square, you can simply calculate the square root of a given number. If the square root is an integer, your number is the perfect square. Let's calculate the squares of the following numbers: 49 and 53 . √49 = 7 - 7 is an integer → number 49 is a perfect square.

How do you check if a number is a perfect square C#?

double result = Math. Sqrt(numberToCheck); bool isSquare = result%1 == 0; isSquare should now be true for all squares, and false for all others.


1 Answers

bool IsPerfectSquare(long input) {     long closestRoot = (long) Math.Sqrt(input);     return input == closestRoot * closestRoot; } 

This may get away from some of the problems of just checking "is the square root an integer" but possibly not all. You potentially need to get a little bit funkier:

bool IsPerfectSquare(long input) {     double root = Math.Sqrt(input);      long rootBits = BitConverter.DoubleToInt64Bits(root);     long lowerBound = (long) BitConverter.Int64BitsToDouble(rootBits-1);     long upperBound = (long) BitConverter.Int64BitsToDouble(rootBits+1);      for (long candidate = lowerBound; candidate <= upperBound; candidate++)     {          if (candidate * candidate == input)          {              return true;          }     }     return false; } 

Icky, and unnecessary for anything other than really large values, but I think it should work...

like image 116
Jon Skeet Avatar answered Oct 19 '22 23:10

Jon Skeet