0

I'm doing an exercise on codewars and I'm supposed to find out if a number is a perfect square. I got the code done for the most part and it works most of the time, but when returning False, i get the wrong answer.

def is_square(n):  
    if n<0:
        return False
    if n == 0:
        return True
    if n>1:
        for i in range(0,n):
            if i*i==n:
                return True
            else:
                return False

If I remove the last else statement, 4 and 25 return true, but when I add in the last else statement, it says 4 and 25 are false. How would I go about fixing it so it returns false if 27 is entered while maintaining 25 to be true?

martineau
  • 119,623
  • 25
  • 170
  • 301
accelerate
  • 51
  • 10
  • Can you not just check whether the square root is an integer? – jpp May 11 '18 at 22:10
  • You're returning false the first time any `i*i==n` is false. So, it's always going to fail. You need to not _remove_ the last line, but _dedent it_ so that it happens after the `for` loop is done, rather than every time through the loop. – abarnert May 11 '18 at 22:10
  • 1
    @jpp That will raise an `OverflowError` for numbers too big to fit in a `float`, and, worse, silently give you the wrong answer for everything small enough to fit in a float but not small enough to fit without truncation. – abarnert May 11 '18 at 22:12
  • I don't think either of these is a dup, but [this question](https://stackoverflow.com/questions/32312248/return-vs-print-list) and [this one](https://stackoverflow.com/questions/5864166/return-statement-in-for-loops) explain how `return` works, if that's your confusion here. – abarnert May 11 '18 at 22:14
  • Also, your function is undefined for n=1. – MegaIng May 11 '18 at 22:16

3 Answers3

3

Put the return False after the for loop

def is_square(n):
    if n<0:
        return False
    if n == 0 or n == 1:
        return True
    if n > 1:
        for i in range(0,n):
            if i*i==n:
                return True
    return False
J. Owens
  • 832
  • 7
  • 9
0

How would I go about fixing it so it returns false if 27 is entered while maintaining 25 to be true?

In your code the else statement:

            else:
                return False

is indented so that it the function returns False as soon as i*i doesn't equal n. You need to remove this "else" statement.

You should also add code to deal with n==1, for example

        if n==1:
            return True

You can finish up with a final "return False" at the lowest level of indentation in the function to catch the remainder of non-perfect squares.

You could also consider adding a check that i*i is less than or equal to n in the loop, this will greatly speed up your code when run on large numbers.

So, to sum up: Something like this code will work:

def is_square(n):  
    if n<0:
        return False
    if n == 0:
        return True
    if n == 1:
        return True
    if n>1:
        for i in range(0,n):
            if i*i==n:
                return True
    return False

But something like this code is better (faster):

def is_square(n):  
    if n<0:
        return False
    if n == 0:
        return True
    if n == 1:
        return True
    if n>1:
        for i in range(0,n):
            if i*i==n:
                return True
            if i*i>n:
                break
    return False
hft
  • 1,245
  • 10
  • 29
0

This should work:

def square(n):
    import math
    if (n < 0):
        return False
    if (int(math.sqrt(n)) == math.sqrt(n)):
        return True
    else:
        return False