I want to find all the PRIME numbers up to the given number, and add them to their lists respectively.
The number '100', has 25 primes, whereas I get 1060. What am I doing wrong?
!pip install sympy
import sympy
def count_primes(num):
primes = 0
nonprimes = 0
for x in range(0, num):
if sympy.isprime(x) == True:
primes = primes + x
else:
nonprimes = nonprimes + x
return primes
It seems like your are mixing the listing of primes and the counting.
You can either add all the primes and nonprimes to a list by defining
primes, nonprimes = [],[]
and keep everything else the same. This will just return the list of primes.
If you want to count the primes from 0 to 100, you can change the code in your if and else statement to
primes+=1
and
nonprimes +=1
and you will return the number of primes between 0 and 100.
instead of increasing of "primes" value by 1 you add "x" in "primes" when number is prime
You could this sympy.primerange() function to get a list of all prime numbers and use len() to get total number of primes for that number
def count_primes(num):
primes = list(sympy.primerange(0, num))
length = len(primes)
return length
print(count_primes(100)) #25
The problem lies within this:
if sympy.isprime(x) == True:
primes = primes + x
else:
nonprimes = nonprimes + x
Above, when you are doing primes = primes + x what you are saying is that you want to add the value of the x (a prime number) to the variable primes.
Thus what is happening, when you use 100 as your num your function will return 1060, as this is the sum of all the primes up to 100.
First, if you want to know the total amount of prime numbers up to a certain number, you can use the following:
#define a variable to track the total number of primes
primeTotal = 0
#using the if statement from before
if sympy.isprime(x) == True:
primeTotal += 1
What this does now, is for every instance of a prime number, you will add 1 to the count of prime numbers.
To create a list of prime numbers, you must first define a list, and then add the prime numbers to that list. Again, using the if statement from before:
#defining the list
primeNums = []
if sympy.isprime(x) == True:
primeNums.append(x)
Now what is happening is, for every instance of a prime number x (the prime number) is being added (appended) to the list primeNums. This should solve both your problems.
The final bit of code will look something like this:
import sympy
def count_primes(num):
primesTotal = 0
primeNums = []
for x in range(0, num):
if sympy.isprime(x) == True:
primesTotal += 1
primeNums.append(x)
return primesTotal, primeNums
print(primesTotal, primeNums)
Related
I am trying to calculate prime factors of a number in python python 3.8.2 32bit (when i pass 35 in code its output should be 7,and so on).But for some reason the program does not return any answer (when i click run the cmd does not output anything).But when i run this javascript, the exact same code works there. (Previously i had an array(list) to which i would append prime factors and at last i would pop the last element which worked for smaller numbers , but for really large numbers i would get a Memory error,so i converted it to use only one variable which will be updated for every while loop). What is going on here ??
My code is :
import math
# Computes only prime factors of n
def compute(n):
arr = 0
# Checks if n is divisible by 2, and if it is divisible,returns 2 because there will be no any other
# prime factor.
if n % 2 == 0:
return 2
# Now that 2 is eliminated we only check for odd numbers upto (square root of n)+1
for i in range(1, round(math.sqrt(n)) + 1, 2):
while n % i == 0:
arr = n/i
n /= i
return str(arr)
print(compute(81))
I am a newbie in python so plz tell me if i have made any silly mistakes.
Ty.
For numbers that are not divisible by 2, your code runs into an infinite loop at
while n%i == 0
For numbers that are divisible by 2, your function returns 2. The execution of the return statement exits the function.
Even if you change the while in while n%i == 0 to if n% == 0 the function will not work.
You will have to restructure your code.
An easy fix would be to check for all factors of a number till n/2 + 1 and return the factors (in a list) that are prime (which can be checked using a separate isprime function.
def isprime(n):
for x in range(2,n//2+1):
if n%x==0:
return False
return True
def compute(n):
arr = []
for i in range(2, n//2+1):
if n % i == 0:
if isprime(i):
arr.append(i)
return arr
If you want all prime factors (which i guess) you shouldn't return values before you have all prime factors in a list for example.
And with this programm you only check once for a 2. But 4 has 2*2. Put it in a loop.
So this code saves all prime factors in a list:
from math import sqrt, ceil
def get_prime_factors(n):
prime_factors = []
while n > 1:
for i in range (2, ceil(sqrt(n))+1):
if n % i == 0:
possible_prime_number = i
while True:
for j in range(2, possible_prime_number//2-1):
if possible_prime_number % j == 0:
possible_prime_number //= j
break
prime_factors.append(possible_prime_number)
n //= possible_prime_number
break
return prime_factors
if you only want the highest one replace return prime_factors with return max(prime_factors)
OK. I think counting upto 600 billion is ridiculous(considering that i am on a 32 bit system). So here is the final code that i am setteling on which gives answer in acceptable time upto 99 million, without using any array and only 1 for loop.
from math import ceil
# Computes only prime factors of n
def compute(n):
arr = 0
# Checks if n is divisible by 2, and if it is divisible,sets arr =2
if n % 2 == 0:
arr = 2
# Now that 2 is eliminated we only check for odd numbers upto (square root of n)+1
for i in range(1, ceil(n/2) + 1, 2):
if n % i == 0:
arr = i
n //= i
return str(arr)
print(compute(999999999))
P.S.:- If you see any possible improvement in my code plz tell me.
Given an integer n, the function legendre_n should return the number of prime numbers between n^2 and (n+1)^2.
This is the code I wrote:
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for i in range(n**2, ((n+1)**2)):
if i%2 != 0:
count += 1
return count
print(legendre_n(12)) = > 5 but I'm getting 12
print(legendre_n(3)) => 2 but I'm getting 4
After testing on python tutor, I found out that the condition I set (i%2 != 0) only filters out odd numbers. However, not all odd numbers are prime numbers. I understand that prime numbers should only be divisible by 1 and the number itself, but I'm stucked at setting the correct condition.
This should do the trick:
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for num in range(n**2, ((n+1)**2)):
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
count = num
return count
you want to check either your num is devidable with any other number between 2 and itself (modulo calculation). If not, it is a prime number.
There is no known "fast" computation to determining if a number is prime. The only known methods involve loops of checks (see some of the other answers). This makes prime factorization a key component in cryptography.
The long story short, is that you must define a function like the ones mentioned above, or you must import one. For example, sympy.isprime() is a highly optimized function that probably runs much faster. Of course, if you are going to import the amazing number theory package, why not just do:
import sympy
def legendre_n(n):
count = 0
for _ in sympy.primerange(n**2,(n+1)**2+1):
count += 1
return count
You only need is make a identifier of prime numbers.
you can try this:
def isprime(n):
for i in range(2,n):
if(n%i)==0:return False
return True
def legendre_n(n):
"""Returns the number of primes between n**2 and (n+1)**2"""
count = 0
for i in range(n**2, ((n+1)**2)):
if isprime(i):
count += 1
return count
When substituting x in the get_large function with a large integer such as 600851475143 the program stalls and doesn't return a value. But, when substituting x with a smaller integer such as 20 it returns the result. How can I fix this?
factors = [] # create new empty list
def calc(x):
for n in range(1, x):
if x % n == 0:
factors.append(n) # if x is divisible by n append to factor list
return factors
def get_large(x):
calc(x) # call the returned values in factors list
return calc(x)[-1] # return the last factor in the list
print("The largest factor is: " + str(get_large(600851475143)))
Here is mine. Note that factors is local to calc() so we aren't constantly appending to the previous list.
Also note that get_large() only has to call calc() once. There is no reason to call it twice.
Finally, I replaced your algorithm in calc() with one that should go substantially faster.
def calc(x):
factors = []
i = 2
while i < x:
while x % i == 0:
x /= i
factors += [i]
i += 1
return factors
def get_large(x):
return calc(x)[-1] #return the last factor in the list
print ("The largest factor is: " +str(get_large(600851475143)))
Result, including timing:
$ time python3 x.py
The largest factor is: 1471
real 0m0.065s
user 0m0.020s
sys 0m0.004s
It's probably not broken, just taking a long time. Python is well known for being slow when running big for loops. I would recommend something like the following:
def calc(x):
n = 2
factors = []
while x != n:
if x % n == 0:
factors.append(n) #if x is divisible by n append to factor list
x = x / n #this will safely and quickly reduce your big number
n = 2 #then start back at the smallest potential factor
else:
n = n + 1
return factors #This will return a list of all prime factors
def get_large(x):
bigFactor = x / calc(x)[0]
#The largest factor is just the original
#number divided by its smallest prime factor
return bigFactor
I used 2 as the smallest potential factor because using 1 would get us nowhere :)
if the number itself is not the largest factor, then why to loop till x, it can looped until x/2 .
[Edited]
import math
def get_large(x):
for n in range(2, math.ceil(math.sqrt(x))):
if x % n == 0:
return x / n
return 1
print ("The largest factor is: " +str(get_large(600851475143)))
Your code is too inefficient and so it takes forever to run for large numbers. The above is a more efficient version.
SPOILER ALERT! THIS MAY INFLUENCE YOUR ANSWER TO PROJECT EULER #3
I managed to get a working piece of code but it takes forever to compute the solution because of the large number I am analyzing.
I guess brute force is not the right way...
Any help in making this code more efficient?
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
primeList.append(x)
# Iterate over primeList to check for prime factors of 'number'
for i in primeList:
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
I'll first just address some basic problems in the particular algorithm you attempted:
You don't need to pre-generate the primes. Generate them on the fly as you need them - and you'll also see that you were generating way more primes than you need (you only need to try the primes up to sqrt(600851475143))
# What is the largest prime factor of the number 600851475143
# Set variables
number = 600851475143
primeList = []
primeFactorList = []
def primeList():
# Make list of prime numbers < 'number'
for x in range(2, number+1):
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
# Iterate over primeList to check for prime factors of 'number'
for i in primeList():
if i > number**0.5:
break
if number % i == 0:
primeFactorList.append(i)
# Print largest prime factor of 'number'
print(max(primeFactorList))
By using a generator (see the yield?) PrimeList() could even just return prime numbers forever by changing it to:
def primeList():
x = 2
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 1
Although I can't help but optimize it slightly to skip over even numbers greater than 2:
def primeList():
yield 2
x = 3
while True:
isPrime = True
# Don't calculate for more than the sqrt of number for efficiency
for y in range(2, int(x**0.5)+1):
if x % y == 0:
isPrime = False
break
if isPrime:
yield x
x += 2
If you abandon your initial idea of enumerating the primes and trying them one at a time against number, there is an alternative: Instead deal directly with number and factor it out -- i.e., doing what botengboteng suggests and breaking down the number directly.
This will be much faster because we're now checking far fewer numbers:
number = 600851475143
def factors(num):
factors = []
if num % 2 == 0:
factors.append(2)
while num % 2 == 0:
num = num // 2
for f in range(3, int(num**0.5)+1, 2):
if num % f == 0:
factors.append(f)
while num % f == 0:
num = num // f
# Don't keep going if we're dividing by potential factors
# bigger than what is left.
if f > num:
break
if num > 1:
factors.append(num)
return factors
# grab last factor for maximum.
print(factors(number)[-1])
You can use user defined function such as
def isprime(n):
if n < 2:
return False
for i in range(2,(n**0.5)+1):
if n % i == 0:
return False
return True
it will return boolean values. You can use this function for verifying prime factors.
OR
you can continuously divide the number by 2 first
n = 600851475143
while n % 2 == 0:
print(2),
n = n / 2
n has to be odd now skip 2 in for loop, then print every divisor
for i in range(3,n**0.5+1,2):
while n % i== 0:
print(i)
n = n / i
at this point, n will be equal to 1 UNLESS n is a prime. So
if n > 1:
print(n)
to print itself as the prime factor.
Have fun exploring
First calculate the sqrt of your number as you've done.
number = 600851475143
number_sqrt = (number**0.5)+1
Then in your outermost loop only search for the prime numbers with a value less than the sqrt root of your number. You will not need any prime number greater than that. (You can infer any greater based on your list).
for x in range(2, number_sqrt+1):
To infer the greatest factor just divide your number by the items in the factor list including any combinations between them and determine if the resultant is or is not a prime.
No need to recalculate your list of prime numbers. But do define a function for determining if a number is prime or not.
I hope I was clear. Good Luck. Very interesting question.
I made this code, everything is explained if you have questions feel free to comment it
def max_prime_divisor_of(n):
for p in range(2, n+1)[::-1]: #We try to find the max prime who divides it, so start descending
if n%p is not 0: #If it doesn't divide it does not matter if its prime, so skip it
continue
for i in range(3, int(p**0.5)+1, 2): #Iterate over odd numbers
if p%i is 0:
break #If is not prime, skip it
if p%2 is 0: #If its multiple of 2, skip it
break
else: #If it didn't break it, is prime and divide our number, we got it
return p #return it
continue #If it broke, means is not prime, instead is just a non-prime divisor, skip it
If you don't know: What it does in range(2, n+1)[::-1] is the same as reversed(range(2, n+1)) so it means that instead of starting with 2, it starts with n because we are searching the max prime. (Basically it reverses the list to start that way)
Edit 1: This code runs faster the more divisor it has, otherwise is incredibly slow, for general purposes use the code above
def max_prime_divisor_of(n): #Decompose by its divisor
while True:
try:
n = next(n//p for p in range(2, n) if n%p is 0) #Decompose with the first divisor that we find and repeat
except StopIteration: #If the number doesn't have a divisor different from itself and 1, means its prime
return n
If you don't know: What it does in next(n//p for p in range(2, n) if n%p is 0) is that gets the first number who is divisor of n
I'm having trouble with my code. The question is:
"By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. What is the 10 001st prime number?"
This is what it looks like:
div = 10001
i = 2
count = 0
prime = 0
now = []
while count < div:
for x in range (2,i+1):
if len(now) ==2:
break
elif i%x == 0:
now.append(x)
if len(now)==1:
prime = i
count += 1
now = []
i+=1
print(prime)
I have tried div up to 1000 and it seems to work fine(for div 1000 I receive 7919). However, when I try div = 10001 I get nothing, not even errors. If someone would help me out I would really appreciate it.
Thank you.
# 7 10001st prime
import itertools
def is_prime(n):
for i in range(2, n//2 + 1):
if n % i == 0:
return False
else:
continue
return True
p = 0
for x in itertools.count(1):
if is_prime(x):
if p == 10001:
print(x)
break
p += 1
Try this code:
prime_list = lambda x:[i for i in xrange(2, x+1) if all([i%x for x in xrange(2, int(i**0.5+1))])][10000]
print prime_list(120000)
Lambda in Python defines an anonymous function and xrange is similar to range, defining a range of integer numbers. The code uses list comprehension and goes through the numbers twice up to the square root of the final number (thus i**0.5). Each number gets eliminated if it is a multiple of the number that's in the range count. You are left with a list of prime numbers in order. So, you just have to print out the number with the right index.
With just some simple modifications (and simplifications) to your code, you can compute the number you're looking for in 1/3 of a second. First, we only check up to the square root as #Hashman suggests. Next, we only test and divide by odd numbers, dealing with 2 as a special case up front. Finally, we toss the whole now array length logic and simply take advantage of Python's break logic:
limit = 10001
i = 3
count = 1
prime = 2
while count < limit:
for x in range(3, int(i ** 0.5) + 1, 2):
if i % x == 0:
break
else: # no break
prime = i
count += 1
i += 2
print(prime)
As before, this gives us 7919 for a limit of 1000 and it gives us 104743 for a limit of 10001. But this still is not as fast as a sieve.
m=0
n=None
s=1
while s<=10001:
for i in range(1,m):
if m%i==0:n=i
if n==1:print(m,'is prime',s);s+=1
m+=1