简体   繁体   中英

Removing multiples of a number from a list in Python

I'm new to Python and i'm working on a program which finds the prime factors of a number. My code so far looks like this:

num = int(input('\nEnter a natural number greater than 1: '))
if num <= 1:
    while num <= 1:
        num = int(input('\nI said greater than 1: '))
if num == 2:
    print('\n', num, 'is a prime number.')
else:
    toggle = 0
    flist = []
    for i in range(2, num - 1):
        if num % i == 0:
            flist.append(i)
            toggle = 1
    if toggle == 0:
        print('\n', num, 'is a prime number.')
    if toggle == 1:
        print('\n', num, 'is not a prime number.')
        print('\nIt\'s prime factors are:', flist)

With an input of 30 for example i get this output:

Enter a natural number greater than 1: 30

30 is not a prime number.

It's prime factors are: [2, 3, 5, 6, 10, 15]

The prime factors in this case are 2 , 3 , 5 . How can i remove their multiples ? Thank you.

I would define an extra function to check if a number is prime

def is_prime(n):
    if n>1:
        for i in range(2,n):
            if (n % i)==0:
                return False
    return True

Then I would use it inside you code to check if a number is prime before to add it to the final list of prime factors.

num = int(input('\nEnter a natural number greater than 1: '))
if num <= 1:
    while num <= 1:
        num = int(input('\nI said greater than 1: '))
if num == 2:
    print('\n', num, 'is a prime number.')
else:
    toggle = 0
    flist = []
    for i in range(2, num - 1):
        if num % i == 0:
            if is_prime(i):   # append only prime numbers
                flist.append(i)
            toggle = 1
    if toggle == 0:
        print('\n', num, 'is a prime number.')
    if toggle == 1:
        print('\n', num, 'is not a prime number.')
        print('\nIt\'s prime factors are:', flist)

This gives you the right output:

Enter a natural number greater than 1: 30

 30 is not a prime number.

It's prime factors are: [2, 3, 5]

Here's a solution using the Sieve of Eratosthenes to first find all primes beneath N and then go through those to find all prime factors, this should be pretty efficient

import numpy as np

def findSieve(num):
    allN = np.arange(1,num+1,1)
    mask = allN == allN
    maskN = np.ma.MaskedArray(allN)
    p = 2

    while maskN[p:].count() > 0:
        mask = mask & ((allN%p != 0) | (allN <= p))
        maskN = np.ma.MaskedArray(maskN, mask =~ mask)
        p = maskN[p:].min()

    return np.asarray(maskN[maskN.mask == False])

def findPrimeFactors(num):        
    sieve = findSieve(num)
    flist = []
    num_factored = num
    for i in range(1,len(sieve)) :
        while num_factored % sieve[i] == 0:
            flist.append(sieve[i])
            num_factored = num_factored // sieve[i]
            if num_factored == 1:
                break

    prime = len(flist) == 1
    if prime:
        print('\n', num, 'is a prime number.')
    else:
        print('\n', num, 'is not a prime number.')
        print('\nIt\'s prime factors are:', flist)


num = int(input('\nEnter a natural number greater than 1: '))
findPrimeFactors(num)

You are getting the multiples of your prime factors, such as 6 = 2 × 3, 10 = 2 × 5 and 15 = 3 × 5.

To avoid those, you should divide your initial number by the prime factors as you find them, so that it won't divide again by the multiples of those prime factors.

Also, you should do that repeatedly, since numbers often have an exponent of a prime factor (for instance, 12 = 2² × 3, so you should divide by 2 twice.)

for i in range(2, num):
    while num % i == 0:
        flist.append(i)
        num = num // i
    if num == 1:
        break

When you get to 1, you know you can stop.

There are also other optimizations you can do, for instance when i² is larger than num, you know num must be a prime, since you already divided it by all factors smaller than i.

You can also skip even numbers after 2, since those will never be factors.

Using the simple code above, you'll know that num is a prime whenever flist is empty. (You don't need an extra toggle to track that.) That works, since you're never dividing by num itself, so if you get to the end and haven't divided once, that means it's a prime.

For a number such as 12, your flist will have [2, 2, 3] . If you want the unique prime factors, without repetitions, you can use set(flist) to get rid of the duplicates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM