-2

I have this code:

def has_divisors(n, i=2):
    """
    Check if a number is prime or not
    :param n: Number to check
    :param i: Increasing value that tries to divide
    :return: True if prime, False if not
    """
    if n <= 1:
        return False
    if i + 1 == n:
        return True
    if n <= 2 and n > 0:
        return True
    if n % i == 0:
        return False
    return has_divisors(n, i + 1)

Which tell if a number is prime or not, problem is that it can check if a number is prime up to +- 1500 after that it enters into maximum recursion depth error. Does anyone has any idea how to make this code more efficient (I don't want completely different code, yes I know recursion is not a good idea for this function but I have to use it) Thank you!

azro
  • 53,056
  • 7
  • 34
  • 70
MM1
  • 912
  • 1
  • 10
  • 28
  • 1
    One way is [to increase the max recursion depth](https://stackoverflow.com/questions/3323001/what-is-the-maximum-recursion-depth-in-python-and-how-to-increase-it). That being said you should really remove recursion and use a loop instead. – freakish Dec 17 '19 at 20:41
  • 2
    After 2, you don't have to check any even numbers as factors, and you don't have check any factors whose square is greater then n. – khelwood Dec 17 '19 at 20:41
  • I can't increase the max recursion depth – MM1 Dec 17 '19 at 20:42
  • 1
    This would be a better question for [codereview.se] – G. Anderson Dec 17 '19 at 20:43
  • I agree but I have to deal with this – MM1 Dec 17 '19 at 20:44
  • I know this appears to be a practice exercise (why else is recursion a requirement?), but for others who stumble on this question: a practical option is just to use a library that is already optimized for this. For example, `import sympy` followed by `sympy.isprime( n )` – Jason K Lai Dec 17 '19 at 20:45
  • 1
    [How do I find a prime number using recursion in Python](https://stackoverflow.com/questions/37095508/how-do-i-find-a-prime-number-using-recursion-in-python) second answer has a similar function that can go 1M rather than 1K before hitting max recursion depth. – DarrylG Dec 17 '19 at 20:51
  • Just to state the obvious, there is no need to use recursion to check primality. So the fact that some solution can handle 1M excursions is pointless. – Chris Johnson Dec 17 '19 at 21:10
  • Yes I do know that, It's just that I have this constraint – MM1 Dec 17 '19 at 21:11

3 Answers3

0

I actually made it more efficient by just adding one condition:

def has_divisors(n, i=2):
"""
Check if a number is prime or not
:param n: Number to check
:param i: Increasing value that tries to divide
:return: True if prime, False if not
"""
if n <= 1:
    return False
if i == n:
    return True
if n <= 2 and n > 0:
    return True
if i * i > n:
    return True
if n % i == 0:
    return False
return has_divisors(n, i + 1)

Thanks to everyone who tried to help.

MM1
  • 912
  • 1
  • 10
  • 28
0

Modifying function from How do I find a prime number using recursion in Python

This should have a maximum recursion dept > 1M

Two improvements: only goes to sqrt(N), and only checks odd numbers.

def has_divisors(N, i=3):
  if N <= 2:
      return False
  elif N % 2 == 0:  # even
      return True
  elif i * i > N:  # tried all divisors to sqrt, 
                   # must be prime
      return False

  elif (N % i) == 0:  # i is a divisor
    return True
  else:  # recursively try the next ( odd) divisor
      return has_divisors(N, i + 2)
DarrylG
  • 16,732
  • 2
  • 17
  • 23
0

You don't need to do basic disqualifying tests on every recursion, so to make it more efficient, as you requested, I'd cast it like:

def has_no_divisors(n):

    if n <= 2 or n % 2 == 0:
        return n == 2

    def has_no_divisors_recursive(n, i=3):

        if i * i > n:
            return True

        if n % i == 0:
            return False

        return has_no_divisors_recursive(n, i + 2)

    return has_no_divisors_recursive(n)

By treating 2 as a special case and just test dividing odd numbers, this should also have twice the performance (and half the stack usage) of your revised code.

cdlane
  • 40,441
  • 5
  • 32
  • 81