Check if a number is a perfect square
Asked Answered
B

26

120

How could I check if a number is a perfect square?

Speed is of no concern, for now, just working.


See also: Integer square root in python.

Bobbiebobbin answered 22/3, 2010 at 0:48 Comment(3)
For very large numbers, there is a fast randomized algorithm: petr-mitrichev.blogspot.com/2017/12/a-quadratic-week.htmlEnface
I don't know how fast the method can tell if an integer is a square. This method does not use the square root or Newton's method. It can be found here: math.stackexchange.com/questions/4226869/…Disaffiliate
For an arbitrary solution, see https://mcmap.net/q/181468/-check-if-a-number-is-a-perfect-square.Neilneila
F
143

The problem with relying on any floating point computation (math.sqrt(x), or x**0.5) is that you can't really be sure it's exact (for sufficiently large integers x, it won't be, and might even overflow). Fortunately (if one's in no hurry;-) there are many pure integer approaches, such as the following...:

def is_square(apositiveint):
  x = apositiveint // 2
  seen = set([x])
  while x * x != apositiveint:
    x = (x + (apositiveint // x)) // 2
    if x in seen: return False
    seen.add(x)
  return True

for i in range(110, 130):
   print i, is_square(i)

Hint: it's based on the "Babylonian algorithm" for square root, see wikipedia. It does work for any positive number for which you have enough memory for the computation to proceed to completion;-).

Edit: let's see an example...

x = 12345678987654321234567 ** 2

for i in range(x, x+2):
   print i, is_square(i)

this prints, as desired (and in a reasonable amount of time, too;-):

152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False

Please, before you propose solutions based on floating point intermediate results, make sure they work correctly on this simple example -- it's not that hard (you just need a few extra checks in case the sqrt computed is a little off), just takes a bit of care.

And then try with x**7 and find clever way to work around the problem you'll get,

OverflowError: long int too large to convert to float

you'll have to get more and more clever as the numbers keep growing, of course.

If I was in a hurry, of course, I'd use gmpy -- but then, I'm clearly biased;-).

>>> import gmpy
>>> gmpy.is_square(x**7)
1
>>> gmpy.is_square(x**7 + 1)
0

Yeah, I know, that's just so easy it feels like cheating (a bit the way I feel towards Python in general;-) -- no cleverness at all, just perfect directness and simplicity (and, in the case of gmpy, sheer speed;-)...

Ferrante answered 22/3, 2010 at 1:20 Comment(18)
Say what you want about the author, gmpy sounds like a great tool for this task.Hugo
The Babylonian method works well, but you need to have special cases for 0 and 1 to avoid division by zero.Transpadane
By the way, set([x]) = {x}Amylaceous
Isn't the set ovekill? Doesn't Babylonian just converge to int(sqrt(x)), where we just have to check if prev != next?Chanellechaney
"I know, that's just so easy it feels like cheating (a bit the way I feel towards Python in general". Soo true ;)Cancel
did gmpy die? I see this post is from years ago and when I attempt an anconda install of gmpy, it is unavailable on all win64 channels for PY27 or PY3.xFina
Whats wrong with Python? Why is it either easy or cheating? Why wouldnt you go with the simpler and more effective language? I dont get it. Is Python not the preferred language among mathematicians and scientists nowadays?Ashanti
Im curious to know how quickly your algorithm runs. What are typical speeds?Ashanti
@Alex There are a few things you can do to improve speed. Firstly, use >>1 instead of //2. The savings is modest but there is some. Secondly, and more importantly, improve your initial guess x. Simply cutting n into 1/4 rather than 1/2 is a serious improvement already for large n. But I recommend more advanced solutions for an initial guess. Such as dividing the exponent of n=k*10^e in half and using x = 5*10^(e//2). Huge improvement. I did this by s = ((len(str((n)))-1)>>1)+1 and x = (10**s)>>1. I cut the run-time of your original code in half, at least on my machine.Ashanti
Perhaps python has moved on since this answer was first made, but the stated solution at the top of the answer is overengineered for no net accuracy benefit vs. the simplest use of math.sqrt see: import math test = 9.000000000000001 print(is_square(test)) print(math.sqrt(test)%1 == 0) They both error on the same precision level...Googins
here is another good explanation to this algorithm blogs.sas.com/content/iml/2016/05/16/…Bemba
gmpy's link is deadSoler
fails for apositiveint=1 which is square rootGudgeon
@Mark_Anderson: Your solution only works for "small" numbers, whereas python integers are arbitrary precision. This solution is only limited only by the available memory.Gismo
For reference, here is the link to gmpy (v2): pypi.org/project/gmpy2Liegnitz
And I have %timeit all answers as of today, and by far gmpy is the fastestLiegnitz
@TomaszGandor the problem is that prev may oscillate between two values, so next is never equal to prev. For example, if you try apositiveint = 80, prev will be 8... 9... 8... 9...Acetylide
@KyleChatman wow, your're right! I wonder if your example (80) has something to do with being $n^2 - 1$... Still, I don't like this $O(\log n)$ memory. A ring buffer of two last should work and be $O(2)$ size ;) I don't want to be shown wrong again, so I'll refrain from proposing quick fix ideas like next >= prev or next in (prev, prev+1) ;) Thanks for the lesson.Chanellechaney
G
63

Use Newton's method to quickly zero in on the nearest integer square root, then square it and see if it's your number. See isqrt.

Python ≥ 3.8 has math.isqrt. If using an older version of Python, look for the "def isqrt(n)" implementation here.

import math

def is_square(i: int) -> bool:
    return i == math.isqrt(i) ** 2
Gismo answered 22/3, 2010 at 1:26 Comment(5)
The perfect square must be a positive integer. Our method does not check whether a number is positive, So it's not valid for all situations.Neilneila
@RezaKGhazi: The code above raises an exception when i is negative, and I think that is the correct behavior, as opposed to returning False.Gismo
Second, this is only a helper function that could be used in a larger application. Raising errors should happen at the application level, not for any individual helper function. Having a try-except block everywhere and for any function reduces efficiency. So error handling is good, but in an optimized way. These types of functions should simply behave to make sure that efficiency is still applied.Neilneila
@RezaKGhazi: Firstly, false -- my function supports arbitrary precision integers because python does as well as math.isqrt(). There is no 64-bit limit, I don't know where you get that information from. Secondly, whether you think asking if a negative number is a perfect square is a legitimate question or a bug is a design decision. I think it's a bug, so I'm content to throw an exception rather than return False.Gismo
My apologies; I thought you used math.sqrt(), not math.isqrt(). So, yes, your function supports large integers. I deleted my first comment. Second, it goes beyond the technique, and your programming style is not discussable.Neilneila
A
23

If youre interested, I have a pure-math response to a similar question at math stackexchange, "Detecting perfect squares faster than by extracting square root".

My own implementation of isSquare(n) may not be the best, but I like it. Took me several months of study in math theory, digital computation and python programming, comparing myself to other contributors, etc., to really click with this method. I like its simplicity and efficiency though. I havent seen better. Tell me what you think.

def isSquare(n):
    ## Trivial checks
    if type(n) != int:  ## integer
        return False
    if n < 0:      ## positivity
        return False
    if n == 0:      ## 0 pass
        return True

    ## Reduction by powers of 4 with bit-logic
    while n&3 == 0:    
        n=n>>2

    ## Simple bit-logic test. All perfect squares, in binary,
    ## end in 001, when powers of 4 are factored out.
    if n&7 != 1:
        return False

    if n==1:
        return True  ## is power of 4, or even power of 2


    ## Simple modulo equivalency test
    c = n%10
    if c in {3, 7}:
        return False  ## Not 1,4,5,6,9 in mod 10
    if n % 7 in {3, 5, 6}:
        return False  ## Not 1,2,4 mod 7
    if n % 9 in {2,3,5,6,8}:
        return False  
    if n % 13 in {2,5,6,7,8,11}:
        return False  

    ## Other patterns
    if c == 5:  ## if it ends in a 5
        if (n//10)%10 != 2:
            return False    ## then it must end in 25
        if (n//100)%10 not in {0,2,6}: 
            return False    ## and in 025, 225, or 625
        if (n//100)%10 == 6:
            if (n//1000)%10 not in {0,5}:
                return False    ## that is, 0625 or 5625
    else:
        if (n//10)%4 != 0:
            return False    ## (4k)*10 + (1,9)


    ## Babylonian Algorithm. Finding the integer square root.
    ## Root extraction.
    s = (len(str(n))-1) // 2
    x = (10**s) * 4

    A = {x, n}
    while x * x != n:
        x = (x + (n // x)) >> 1
        if x in A:
            return False
        A.add(x)
    return True

Pretty straight forward. First it checks that we have an integer, and a positive one at that. Otherwise there is no point. It lets 0 slip through as True (necessary or else next block is infinite loop).

The next block of code systematically removes powers of 4 in a very fast sub-algorithm using bit shift and bit logic operations. We ultimately are not finding the isSquare of our original n but of a k<n that has been scaled down by powers of 4, if possible. This reduces the size of the number we are working with and really speeds up the Babylonian method, but also makes other checks faster too.

The third block of code performs a simple Boolean bit-logic test. The least significant three digits, in binary, of any perfect square are 001. Always. Save for leading zeros resulting from powers of 4, anyway, which has already been accounted for. If it fails the test, you immediately know it isnt a square. If it passes, you cant be sure.

Also, if we end up with a 1 for a test value then the test number was originally a power of 4, including perhaps 1 itself.

Like the third block, the fourth tests the ones-place value in decimal using simple modulus operator, and tends to catch values that slip through the previous test. Also a mod 7, mod 8, mod 9, and mod 13 test.

The fifth block of code checks for some of the well-known perfect square patterns. Numbers ending in 1 or 9 are preceded by a multiple of four. And numbers ending in 5 must end in 5625, 0625, 225, or 025. I had included others but realized they were redundant or never actually used.

Lastly, the sixth block of code resembles very much what the top answerer - Alex Martelli - answer is. Basically finds the square root using the ancient Babylonian algorithm, but restricting it to integer values while ignoring floating point. Done both for speed and extending the magnitudes of values that are testable. I used sets instead of lists because it takes far less time, I used bit shifts instead of division by two, and I smartly chose an initial start value much more efficiently.

By the way, I did test Alex Martelli's recommended test number, as well as a few numbers many orders magnitude larger, such as:

x=1000199838770766116385386300483414671297203029840113913153824086810909168246772838680374612768821282446322068401699727842499994541063844393713189701844134801239504543830737724442006577672181059194558045164589783791764790043104263404683317158624270845302200548606715007310112016456397357027095564872551184907513312382763025454118825703090010401842892088063527451562032322039937924274426211671442740679624285180817682659081248396873230975882215128049713559849427311798959652681930663843994067353808298002406164092996533923220683447265882968239141724624870704231013642255563984374257471112743917655991279898690480703935007493906644744151022265929975993911186879561257100479593516979735117799410600147341193819147290056586421994333004992422258618475766549646258761885662783430625 ** 2
for i in range(x, x+2):
    print(i, isSquare(i))

printed the following results:

1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890625 True
1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890626 False

And it did this in 0.33 seconds.

In my opinion, my algorithm works the same as Alex Martelli's, with all the benefits thereof, but has the added benefit highly efficient simple-test rejections that save a lot of time, not to mention the reduction in size of test numbers by powers of 4, which improves speed, efficiency, accuracy and the size of numbers that are testable. Probably especially true in non-Python implementations.

Roughly 99% of all integers are rejected as non-Square before Babylonian root extraction is even implemented, and in 2/3 the time it would take the Babylonian to reject the integer. And though these tests dont speed up the process that significantly, the reduction in all test numbers to an odd by dividing out all powers of 4 really accelerates the Babylonian test.

I did a time comparison test. I tested all integers from 1 to 10 Million in succession. Using just the Babylonian method by itself (with my specially tailored initial guess) it took my Surface 3 an average of 165 seconds (with 100% accuracy). Using just the logical tests in my algorithm (excluding the Babylonian), it took 127 seconds, it rejected 99% of all integers as non-Square without mistakenly rejecting any perfect squares. Of those integers that passed, only 3% were perfect Squares (a much higher density). Using the full algorithm above that employs both the logical tests and the Babylonian root extraction, we have 100% accuracy, and test completion in only 14 seconds. The first 100 Million integers takes roughly 2 minutes 45 seconds to test.

EDIT: I have been able to bring down the time further. I can now test the integers 0 to 100 Million in 1 minute 40 seconds. A lot of time is wasted checking the data type and the positivity. Eliminate the very first two checks and I cut the experiment down by a minute. One must assume the user is smart enough to know that negatives and floats are not perfect squares.

Ashanti answered 16/8, 2017 at 23:38 Comment(7)
As for simplicity, it's hard to beat the accepted answer. Performance-wise, yours should be better. I'm skeptical of the value of reducing the target by square powers of small primes, but computing jacobi symbols for small primes should be a win. And the larger the numbers the bigger the advantage for this answer.Gismo
Reduction by powers of small primes is necessary for the jacobi symbol computation to provide deterministic results. Otherwise its at best probabilistic, or deterministic for non-squareness, but does not verify squareness. Thats partially why I do factoring by powers of squares; the only jacobi symbols I calculate are for the same small primes I factor out. I also do it simply to reduce the size of the test number to make the Babylonian method used later a bit faster (but that is debatable).Ashanti
Well, it's certainly a good and unique answer and if I have some time in the future I'd like to play around with this, try some timings varying the number of small primes to see if an optimum number can be found at a given bitsize.Gismo
By all means, test my code. Break it. Im not a programmer by trade, Im a math major. Python is just a hobby. Id be curious if its any more efficient on average.Ashanti
@JamesKPolk Upon reevaluation and a time comparison test I came to the conclusion that indeed Jacobi test and the reduction by powers of primes do not save sufficient time to be worthwhile. Though I still reduce by powers of 4 to great effect. I have changed my answer, added a few new tests, and provided a time-comparison evaluation of my results. The time comparison is amazing compared to the accepted answer.Ashanti
If you are still interested in there is essentially a duplicate question here with some interesting answers , especially A.Rex's answer.Gismo
I implemented this solution in Java, and 25 is failing this test, unless I missed something. Do you need to add n to the set A?Octodecimo
H
22

Since you can never depend on exact comparisons when dealing with floating point computations (such as these ways of calculating the square root), a less error-prone implementation would be

import math

def is_square(integer):
    root = math.sqrt(integer)
    return integer == int(root + 0.5) ** 2

Imagine integer is 9. math.sqrt(9) could be 3.0, but it could also be something like 2.99999 or 3.00001, so squaring the result right off isn't reliable. Knowing that int takes the floor value, increasing the float value by 0.5 first means we'll get the value we're looking for if we're in a range where float still has a fine enough resolution to represent numbers near the one for which we are looking.

Hugo answered 22/3, 2010 at 1:39 Comment(8)
It would be slightly better to just do if int(root + 0.5) ** 2 == integer: if int acts as floor for the numbers we care about.Privilege
@David Johnstone, I changed this post to use that implementation, which I agree is nicer than the old way I had. In any event, some of the other techniques others mention here are even better and more reliable.Hugo
I understand that FP is approximate, but can math.sqrt(9) really ever be 2.99999? Python's float maps to C's double, but I think even a 16-bit FP type has more precision than that, so maybe if you had a C compiler that used 8-bit FP ("minifloats") as its double type? I suppose it's technically possible, but it seems unlikely to me that that's the case on any computer running Python today.Choriamb
@Ken, I said "something like" to indicate I was getting at the underlying concept; it is not guaranteed that the value you get won't be slightly less than the exact value. I cannot imagine that math.sqrt(9) will return 2.99999 on any particular system, but the actual result is system-dependent and cannot be expected to be exact.Hugo
Sorry, I took "like" to mean "for example" rather than "in the neighborhood". Another casualty of the war between English and mathematics!Choriamb
For a concrete example of floating point rounding problems I think you need to get large. For example the lovely square number 10000000000000000200000000000000001: this can't be represented exactly with a 64-bit IEEE float, which will result in a false negative from the algorithm on most platforms.Judiejudith
This function is incorrect for a large square such as 152415789666209426002111556165263283035677489.Froufrou
Another issue with this method is that it raises an exception OverflowError: int too large to convert to float for integers larger than about 1023 bits. Numbers that size or larger are common in cryptography. Of course you check for overflow and do something else in that case.Gismo
S
14
import math

def is_square(n):
    sqrt = math.sqrt(n)
    return (sqrt - int(sqrt)) == 0

A perfect square is a number that can be expressed as the product of two equal integers. math.sqrt(number) return a float. int(math.sqrt(number)) casts the outcome to int.

If the square root is an integer, like 3, for example, then math.sqrt(number) - int(math.sqrt(number)) will be 0, and the if statement will be False. If the square root was a real number like 3.2, then it will be True and print "it's not a perfect square".

It fails for a large non-square such as 152415789666209426002111556165263283035677490.

Strangle answered 1/6, 2016 at 9:58 Comment(3)
Change if (math.sqrt(number)-int(math.sqrt(number))): to a=math.sqrt(number) then another line for: if a-int(a):. This is since it only has to calculate the square root once, which imo for large n is significantLarrigan
@JamesKPolk Why is that?Blab
Im pretty sure sqrt - int(sqrt) is identical to sqrt%1. Your entire function could just be return math.sqrt(n)%1==0Ashanti
C
9

My answer is:

def is_square(x):
    return x**.5 % 1 == 0

It basically does a square root, then modulo by 1 to strip the integer part and if the result is 0 return True otherwise return False. In this case x can be any large number, just not as large as the max float number that python can handle: 1.7976931348623157e+308

It is incorrect for a large non-square such as 152415789666209426002111556165263283035677490.

Carpometacarpus answered 30/9, 2017 at 4:54 Comment(0)
A
8

This can be solved using the decimal module to get arbitrary precision square roots and easy checks for "exactness":

import math
from decimal import localcontext, Context, Inexact

def is_perfect_square(x):
    # If you want to allow negative squares, then set x = abs(x) instead
    if x < 0:
        return False

    # Create localized, default context so flags and traps unset
    with localcontext(Context()) as ctx:
        # Set a precision sufficient to represent x exactly; `x or 1` avoids
        # math domain error for log10 when x is 0
        ctx.prec = math.ceil(math.log10(x or 1)) + 1  # Wrap ceil call in int() on Py2
        # Compute integer square root; don't even store result, just setting flags
        ctx.sqrt(x).to_integral_exact()
        # If previous line couldn't represent square root as exact int, sets Inexact flag
        return not ctx.flags[Inexact]

For demonstration with truly huge values:

# I just kept mashing the numpad for awhile :-)
>>> base = 100009991439393999999393939398348438492389402490289028439083249803434098349083490340934903498034098390834980349083490384903843908309390282930823940230932490340983098349032098324908324098339779438974879480379380439748093874970843479280329708324970832497804329783429874329873429870234987234978034297804329782349783249873249870234987034298703249780349783497832497823497823497803429780324
>>> sqr = base ** 2
>>> sqr ** 0.5  # Too large to use floating point math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: int too large to convert to float

>>> is_perfect_power(sqr)
True
>>> is_perfect_power(sqr-1)
False
>>> is_perfect_power(sqr+1)
False

If you increase the size of the value being tested, this eventually gets rather slow (takes close to a second for a 200,000 bit square), but for more moderate numbers (say, 20,000 bits), it's still faster than a human would notice for individual values (~33 ms on my machine). But since speed wasn't your primary concern, this is a good way to do it with Python's standard libraries.

Of course, it would be much faster to use gmpy2 and just test gmpy2.mpz(x).is_square(), but if third party packages aren't your thing, the above works quite well.

Apollinaire answered 22/6, 2016 at 1:38 Comment(0)
P
7

I just posted a slight variation on some of the examples above on another thread (Finding perfect squares) and thought I'd include a slight variation of what I posted there here (using nsqrt as a temporary variable), in case it's of interest / use:

import math

def is_square(n):
  if not (isinstance(n, int) and (n >= 0)):
    return False 
  else:
    nsqrt = math.sqrt(n)
    return nsqrt == math.trunc(nsqrt)

It is incorrect for a large non-square such as 152415789666209426002111556165263283035677490.

Powdery answered 21/4, 2011 at 22:4 Comment(0)
H
4

A variant of @Alex Martelli's solution without set

When x in seen is True:

  • In most cases, it is the last one added, e.g. 1022 produces the x's sequence 511, 256, 129, 68, 41, 32, 31, 31;
  • In some cases (i.e., for the predecessors of perfect squares), it is the second-to-last one added, e.g. 1023 produces 511, 256, 129, 68, 41, 32, 31, 32.

Hence, it suffices to stop as soon as the current x is greater than or equal to the previous one:

def is_square(n):
    assert n > 1
    previous = n
    x = n // 2
    while x * x != n:
        x = (x + (n // x)) // 2
        if x >= previous:
            return False
        previous = x
    return True

x = 12345678987654321234567 ** 2
assert not is_square(x-1)
assert is_square(x)
assert not is_square(x+1)

Equivalence with the original algorithm tested for 1 < n < 10**7. On the same interval, this slightly simpler variant is about 1.4 times faster.

Homoiousian answered 13/3, 2020 at 9:30 Comment(0)
S
3

This is my method:

def is_square(n) -> bool:
    return int(n**0.5)**2 == int(n)

Take square root of number. Convert to integer. Take the square. If the numbers are equal, then it is a perfect square otherwise not.

It is incorrect for a large square such as 152415789666209426002111556165263283035677489.

Songful answered 18/7, 2017 at 10:51 Comment(1)
Won't work for negative numbers but still a great solution!Churrigueresque
L
3

If the modulus (remainder) leftover from dividing by the square root is 0, then it is a perfect square.

def is_square(num: int) -> bool:
    return num % math.sqrt(num) == 0

I checked this against a list of perfect squares going up to 1000.

Libidinous answered 7/2, 2020 at 21:40 Comment(0)
C
3

It is possible to improve the Babylonian method by observing that the successive terms form a decreasing sequence if one starts above the square root of n.

def is_square(n):
    assert n > 1
    a = n
    b = (a + n // a) // 2
    while b < a:
        a = b
        b = (a + n // a) // 2
    return a * a == n
Chirography answered 26/7, 2021 at 10:26 Comment(0)
C
3

If it's a perfect square, its square root will be an integer, the fractional part will be 0, we can use modulus operator to check fractional part, and check if it's 0, it does fail for some numbers, so, for safety, we will also check if it's square of the square root even if the fractional part is 0.

import math

def isSquare(n):
    root = math.sqrt(n)
    if root % 1 == 0:
        if int(root) * int(root) == n:
            return True
    return False

isSquare(4761)
Camus answered 1/1, 2022 at 5:38 Comment(0)
P
2

You could binary-search for the rounded square root. Square the result to see if it matches the original value.

You're probably better off with FogleBirds answer - though beware, as floating point arithmetic is approximate, which can throw this approach off. You could in principle get a false positive from a large integer which is one more than a perfect square, for instance, due to lost precision.

Planoconcave answered 22/3, 2010 at 1:6 Comment(0)
C
2

A simple way to do it (faster than the second one) :

def is_square(n):  
     return str(n**(1/2)).split(".")[1] == '0'

Another way:

def is_square(n):   
    if n == 0:
        return True
    else:
        if n % 2 == 0 :
            for i in range(2,n,2):
                if i*i == n:
                    return True
        else :
            for i in range(1,n,2):
                if i*i == n:
                    return True
    return False
Cletuscleve answered 31/5, 2022 at 9:46 Comment(0)
N
2

This is an elegant, simple, fast and arbitrary solution that works for Python version >= 3.8:

Version 1:

from math import isqrt

def is_square(number):
    if number >= 0:
        return isqrt(number) ** 2 == number
    return False

Version 2:

def is_square2(number):
    return isqrt(number) ** 2 == number if number >= 0 else False

This version follows the same analogy but is at least 68% faster than the previous version.

Neilneila answered 21/2, 2023 at 22:44 Comment(0)
G
0

This response doesn't pertain to your stated question, but to an implicit question I see in the code you posted, ie, "how to check if something is an integer?"

The first answer you'll generally get to that question is "Don't!" And it's true that in Python, typechecking is usually not the right thing to do.

For those rare exceptions, though, instead of looking for a decimal point in the string representation of the number, the thing to do is use the isinstance function:

>>> isinstance(5,int)
True
>>> isinstance(5.0,int)
False

Of course this applies to the variable rather than a value. If I wanted to determine whether the value was an integer, I'd do this:

>>> x=5.0
>>> round(x) == x
True

But as everyone else has covered in detail, there are floating-point issues to be considered in most non-toy examples of this kind of thing.

Glomerulus answered 23/3, 2010 at 2:17 Comment(1)
What does "this applies to the variable rather than a value" mean? You can use round(5.0) == 5.0 and isinstance(x, int) without problems. (And the OOWTDI is just to call x.is_integer().)Fagaceous
T
0

If you want to loop over a range and do something for every number that is NOT a perfect square, you could do something like this:

def non_squares(upper):
    next_square = 0
    diff = 1
    for i in range(0, upper):
        if i == next_square:
            next_square += diff
            diff += 2
            continue
        yield i

If you want to do something for every number that IS a perfect square, the generator is even easier:

(n * n for n in range(upper))
Tomb answered 30/1, 2017 at 20:51 Comment(0)
F
0

I think that this works and is very simple:

import math

def is_square(num):
    sqrt = math.sqrt(num)
    return sqrt == int(sqrt)

It is incorrect for a large non-square such as 152415789666209426002111556165263283035677490.

Flipflop answered 28/8, 2017 at 7:44 Comment(1)
This is same as above answer.Ja
H
0
a=int(input('enter any number'))
flag=0
for i in range(1,a):
    if a==i*i:
        print(a,'is perfect square number')
        flag=1
        break
if flag==1:
    pass
else:
    print(a,'is not perfect square number')
Heir answered 7/5, 2020 at 17:44 Comment(1)
Although this code might solve the problem, a good answer should also explain what the code does and how it helps.Cosmography
C
0

In kotlin :

It's quite easy and it passed all test cases as well.

really thanks to >> https://www.quora.com/What-is-the-quickest-way-to-determine-if-a-number-is-a-perfect-square

fun isPerfectSquare(num: Int): Boolean {
    var result = false
    
    var sum=0L
    var oddNumber=1L
    
     while(sum<num){
         sum = sum + oddNumber
         oddNumber = oddNumber+2
     }
     
    result = sum == num.toLong()
    
 return result   
}
Camara answered 10/5, 2022 at 4:48 Comment(0)
T
0
def isPerfectSquare(self, num: int) -> bool:
    left, right = 0, num
    while left <= right:
        mid = (left + right) // 2
        if mid**2 < num:
            left = mid + 1
        elif mid**2 > num:
            right = mid - 1
        else:
            return True
    return False
Trudi answered 26/5, 2022 at 22:16 Comment(0)
L
0

Probably the easiest way is to say

def perfectSquare(x):
   return (x == math.isqrt(x) ** 2)

This algorithm is fairly fast already, since it uses Newton Method to find the integer square root. However, one can identify a lot of numbers that will never be a square. For example when you take x % 16, only remainders of 0, 1, 4, 9 need to be checked against the isqrt(x) method. If the isqrt-method is not available, one can also use the idea of the Babylonian method and combine it with the modulo idea to come up with

def perfectSquare(n):
    m = n % 16
    if m != 0 and m != 1 and m != 4 and m != 9:
      return False
    x = n
    while x * x > n:
        x = (x + n // x) // 2
    return x * x == n
Lunette answered 17/5, 2023 at 15:37 Comment(0)
P
-1
  1. Decide how long the number will be.
  2. take a delta 0.000000000000.......000001
  3. see if the (sqrt(x))^2 - x is greater / equal /smaller than delta and decide based on the delta error.
Physics answered 22/3, 2010 at 3:6 Comment(0)
M
-3
import math

def is_square(n):
    sqrt = math.sqrt(n)
    return sqrt == int(sqrt)

It fails for a large non-square such as 152415789666209426002111556165263283035677490.

Maag answered 12/3, 2017 at 9:58 Comment(3)
This is a code only answer. Please provide a bit of reasoning.Hord
You cant reason your way through that @Hord ? It makes perfect sense and Im not even an expert in python. Its not the greatest test but it is valid both in theory and for small cases.Ashanti
@CogitoErgoCogitoSum: You don't understand. Code-only answers don't get found by searches using search engines like google. Whether one can understand the answer is irrelevant.Gismo
P
-3

The idea is to run a loop from i = 1 to floor(sqrt(n)) then check if squaring it makes n.

bool isPerfectSquare(int n) 
{ 
    for (int i = 1; i * i <= n; i++) { 

        // If (i * i = n) 
        if ((n % i == 0) && (n / i == i)) { 
            return true; 
        } 
    } 
    return false; 
} 
Paratrooper answered 13/5, 2020 at 11:16 Comment(1)
This is a Python questionInsatiable

© 2022 - 2024 — McMap. All rights reserved.