Creating a function that returns prime numbers under a given maximum?

Viewed 48

Instructions are to write a function that returns all prime numbers below a certain max number. The function is_factor was already given, I wrote everything else. When I run the code I don't get an error message or anything, it's just blank. I'm assuming there's something I'm missing but I don't know what that is.

def is_factor(d, n):
""" True if `d` is a divisor of `n` """
  return n % d == 0
def return_primes(max):
  result = []
  i = 0
  while i < max:
    if is_factor == True:
      return result
    i += 1
2 Answers

You should test each i against all divisors smaller than math.sqrt(i). Use the inner loop for that. any collects the results. Don't return result right away, for you should fill it first.

def return_primes(max):
    result = []
    for i in range(2, max):
        if not any(is_factor(j, i) for j in range(2, int(math.sqrt(i)) + 1)):
            result.append(i)
    return result

print(return_primes(10))

As a side note, use for and range rather than while to make less mistakes and make your code more clear.

The reason that your code is returning blank when you run it, is because you are comparing a function type to the value of True, rather than calling it.

    print(is_factor)
    <function is_factor at 0x7f8c80275dc0>

In other words, you are doing a comparison between the object itself rather than invoking the function.

Instead, if you wanted to call the function and check the return value from it, you would have to use parenthesis like so:

    if(is_factor(a, b) == True):

or even better

    if(is_factor(a, b)):

which will inherently check whether or not the function returns True without you needing to specify it.

Additionally, you are not returning anything in your code if the condition does not trigger. I recommend that you include a default return statement at the end of your code, not only within the condition itself.

Now, in terms of the solution to your overall problem and question; "How can I write a program to calculate the prime numbers below a certain max value?"

To start, a prime number is defined by "any number greater than 1 that has only two factors, 1 and itself."

https://www.splashlearn.com/math-vocabulary/algebra/prime-number

This means that you should not include 1 in the loop, otherwise every single number is divisible by 1 and this can mess up the list you are trying to create.

My recommendation is to start counting from 2 instead, then you can add 1 as a prime number at the end of the function.

Before going over the general answer and algorithm, there are some issues in your code I'd like to address:

  1. It is recommended to use a different name for your variable other than max, because max() is a function in python that is commonly used.
  2. Dividing by 0 is invalid and can break the math within your program. It is a good idea to check the number you are dividing by to ensure it is not zero to make sure you do not run into math issues. Alternatively, if you start your count from 2 upwards, you won't have this issue.
  3. Currently you are not appending anything into your results array, which means no results will be returned. My recommendation is to add the prime number into the results array once it is found.
  4. Right now, you return the results array as soon as you have calculated the first result. This is a problem because you are trying to capture all of the prime numbers below a specific number, and hence you need more than one result.

You can fix this by returning the results array at the end of the function, not in between, and making sure to append each of the prime numbers as you discover them.

  1. You need to check every single number between 2 and the max number to see if it is prime. Your current code only checks the max number itself and not the numbers in between.

Now I will explain my recommended answer and the algorithm behind it;

    def is_factor(d, n):
      print("Checking if " + str(n) + " is divisible by " + str(d))
      print(n % d == 0)
      return n % d == 0

    def return_primes(max_num):
      result = []
      for q in range(2, max_num+1):
        count_number_of_trues = 0

        for i in range(2, q):
          if(i != q):
            if(is_factor(i, q)):
              print("I " + str(i) + " is a factor of Q " + str(q))
              count_number_of_trues += 1
        if(q not in result and count_number_of_trues == 0):
            result.append(q)  

      result.append(1)

      return sorted(result)

    print(return_primes(10))

The central algorithm is that you want to start counting from 2 all the way up to your max number. This is represented by the first loop.

Then, for each of these numbers, you should check every single number from 2 up to that number to see if a divisor exists.

Then, you should count the number of times that the second number is a factor of the first number, and if you get 0 times at the end, then you know it must be a prime number.

    Example:

    Q=10

    "Is I a factor of Q?"
    I:
    9 - False
    8 - False
    7 - False
    6 - False
    5 - True
    4 - False
    3 - False
    2 - True

So for the number 10, we can see that there are 2 factors, 5 and 2 (technically 3 if you include 1, but that is saved for later).

Thus, because 10 has 2 factors [excluding 1] it cannot be prime.

Now let's use 7 as the next example.

    Example:

    Q=7

    "Is I a factor of Q?"
    I:     
    6 - False
    5 - False
    4 - False
    3 - False
    2 - False

Notice how every number before 7 all the way down to 2 is NOT a factor, hence 7 is prime.

So all you need to do is loop through every number from 2 to your max number, then within another loop, loop through every number from 2 up to that current number.

Then count the total number of factors, and if the count is equal to 0, then you know the number must be prime.

Some additional recommendations:

  • although while loops will do the same thing as for loops, for loops are often more convenient to use in python because they initialize the counts for you and can save you some lines of code. Also, for loops will take care of the incrementing process for you so there is no risk of forgetting.
  • I recommend sorting the list when you return it, it looks nicer that way.
  • Before adding the prime factor into your results list, check to see if it is already in the list so you don't run into a scenario where multiples of the same number is added (like [2,2,2] for example)

Please note that there are many different ways to implement this, and my example is but one of many possible answers.

Related