Python several billion iteration loop - python

I'm new to programming, so please bear with me.
I wrote this code to find the largest prime factor of a number, but when I input a number of a billion or greater it doesn't solve. I've tried xrange, but I'm using Python 3.4. Can anyone point me in the right direction?
done = False
num = int(input("Enter a number: "))
for j in range(num,2,-1):
if (num % j) != 0:
continue
for i in range(2,j):
if (j % i) != 0:
continue
break
else: break
print(j)

It's an O(n^2) algorithm. It doesn't appear to solve because it's just taking a long time. Solution? Use numpy. Or find a non-naive algorithm, or write one yourself. The sieve of Eratosthenes is a good starting point.

Since you are new to programming, here is a simple solution (but know that there are substantially more complex solutions that are more efficient). First note that you only need to check divisors up to the square root of num, since if num = a * b then one is less than the square root and one is larger. Secondly you only need to check for prime divisors.
You can generate a list of primes as follows:
import math
import itertools
def primes_generator():
"""Generator for the infinite list of primes."""
primes = [2, 3]
for prime in primes:
yield prime
for c in itertools.count(5, 2):
bound = math.sqrt(c)
for p in primes:
if not (c % p):
break
if p > bound:
primes.append(c)
yield c
break
Now to find the all the prime divisors:
def prime_factorization(number, primes=None):
if not primes:
primes = primes_generator()
factorization = dict()
for p in primes:
count = 0
while not (number % p):
number = number / p
count = count + 1
if count:
factorization[p] = count
if number == 1:
return factorization
The largest prime divisor is just the largest key in the dictionary. These functions should work fine for fairly large inputs. On my machine the following takes 0.06 seconds.
print(max(prime_factorization(1000000001).keys()))

Related

Optimize performance - writing out Prime Numbers

The issue is Prime Numbers -that the solution is not implemented effectively.
I hear about eratosthenes sieve.
What are the other methods of implementing prime numbers - in a more efficient way?
n = int(input())
suma = 0
m = 0
while m < n:
if n > 100000:
break
x = int(input())
if 1 < x < 10000:
for i in range(x):
if x % (i + 1) == 0:
suma += 1
if suma == 2 and x != 2:
m += 1
print('o')
suma = 0
else:
m += 1
print('x')
suma = 0
The one of solution: https://medium.com/#dhruvpatel1057/generate-prime-numbers-in-python-using-segmented-sieve-of-eratosthenes-245b79da6687
You are using a very naive approach for primality checking.
As a general naive but not so much method, I'd recommend using Wilson's theorem as prime checker. Using math.factorial instead of a python loop should provide you with some reasonable speed increase while keeping the code fairly simple.
I hear about eratosthenes sieve - but not idea, how to implement it.
That's not the sieve of eratosthenes proper but what people usually talk about when they mention it is that when you find a prime you go through all your candidates and remove its factors ("sieving" them out hence the name) and the new first candidate is the next prime in the sequence.
There are more efficient primality tests than sieving everything though, check the "primality test" wikipedia page for examples.
This code will generate the amount of prime numbers the user asked for. It is very efficient, and can work out the first thousand prime numbers in milliseconds.
amount = int(input("Enter the amount of prime numbers you would like to see: "))
primes = []
num = 1
while len(primes) < amount:
num += 1
# If num is bigger than 1, and is 2 or is odd, and when divided by all the number from 3 to num's square root plus 1 (excluding even numbers), there is always a remainder.
if num > 1 and (num == 2 or num % 2 != 0) and all(num % divisor != 0 for divisor in range(3, int(num ** 0.5) + 1, 2)):
primes.append(num)
print(f"The first {amount} prime numbers are:\n{primes}")
this is sample code , make a list of prime, and from this list check the number to process is getting divided or not , if it is not getting divided then it is prime else it is not
# your code goes here
x = int(input())
prime =[]
for i in range(2,x):
if i not in prime:
if prime == []:
prime.append(i)
else:
check = 1
for j in prime:
if i%j==0:
check = 0
break
if check:
prime.append(i)
print(prime)

Calculating the thousandth prime

The problem asks to calculate the 1000th prime number. I am trying to solve this problem but I am stuck.
There are some guidelines on how to solve the problem.
To help you get started, here is a rough outline of the stages you should probably follow in
writing your code:
Initialize some state variables
Generate all (odd) integers > 1 as candidates to be prime
For each candidate integer, test whether it is prime
One easy way to do this is to test whether any other integer > 1 evenly
divides the candidate with 0 remainder. To do this, you can use modular
arithmetic, for example, the expression a%b returns the remainder after
dividing the integer a by the integer b.
You might think about which integers you need to check as divisors –
certainly you don’t need to go beyond the candidate you are checking, buthow much sooner can you stop checking?
If the candidate is prime, print out some information so you know where you are
in the computation, and update the state variables
Stop when you reach some appropriate end condition. In formulating this
condition, don’t forget that your program did not generate the first prime (2).
Use these ideas to guide the creation of your code.
My attempt so far is this
def calculate_thousandth_prime():
j = 0
for i in range(3,int(10e6)):
if i%2 != 0:
counter = 0
for k in range(1, i):
if i%k != 0:
counter += 1
if counter == 0:
print("This candidate is prime")
j += 1
if j == 1001:
print("The number "+str(i)+" is the thousandth prime")
break
return 0
calculate_thousandth_prime()
My code gets stuck on i%k != 0. I must be doing something wrong... any help?
You have two problems:
First, you're searching for k in range(1, i):. Because every number, including primes, is divisible by 1, you won't find any primes. Try searching range(2, i) instead.
Second, you're checking if i%k != 0:. You should be checking that i%k == 0 instead. If i is divisible by any number k, then the number is not prime.
Actually, I found a third issue: You have an off-by-one error. By initializing j=0, your code considers the first prime it finds to be the "zeroth" prime. The code will output the thousand-and-first prime, instead of the thousandth prime.
Changes I made:
Change your range to add a 2 step to skip even numbers more naturally.
Check your inner loop, you need to divide by the values range(2, i//2). Dividing by anything greater than i//2 will be less than 2.
Change your prime check to see if any number in the above range divides. If so, we know the number is false. At that point we can move onto the next number.
We want to return when the prime counter is 1000, you were returning the 1001th prime.
def calculate_thousandth_prime():
prime_counter = 0
for i in range(3,int(10e6),2):
prime = True
for k in range(2, i//2):
if i % k == 0:
prime = False
break
if prime:
print(str(i) + " is prime")
prime_counter += 1
if prime_counter == 1000:
print("The number "+str(i)+" is the thousandth prime")
break
return i
calculate_thousandth_prime()
The sieve of Eratosthenes is generally the fastest way for the early primes. You can adapt it to reach the nth prime.
For example:
def nthPrime(N):
sieve = [1]*(N**2)
p = 2
for _ in range(N):
while not sieve[p]: p += 1
sieve[p::p] = [0]*len(sieve[p::p])
return p
nthPrime(100) # 541
The prime list divisor check method is probably easier to write and understand but it is much slower (although for only 1000 primes, this wouldn't make much of a difference):
def nthPrime(N):
primes = [2]
p = 1
while len(primes)<N:
p += 2
primes += [p]*all(p%d for d in primes)
return p

Why won't my python code display any output for my algorithm?

I am making an algorithm with python to find perfect numbers up to 100000000000000. I have created some code for this that should do it, and it does not throw up any errors, but the code just outputted nothing and is running continuously. I have checked, and the first perfect number is six, so why is my program taking so long to get there?
Here is my code:
number = 1
divisor = 2
factors = 1
if number < 100000000000000:
while True:
number2 = number/divisor
if isinstance(number2, int):
factors = factors + divisor + number2
divisor = divisor + 1
if divisor == number:
if factors == number:
print(number)
number = number + 1
break
In both of these examples, I used the variable "j" for the target number.
This was my first thought, but please do not use it on anything bigger than 10000:
print([i for i in range(1,j+1) if i == sum(k for k in range(1,i//2+1) if i%k == 0)])
Since perfect numbers cannot be prime, I decided to alter a sieve to reduce the amount of numbers to calculate. The sieve can be found here Sieve of Eratosthenes. There is a good explanation there and on the wiki about the sieve.
def SieveOfEratosthenes(n):
prime = [True for i in range(n+1)]
p = 2
while (p * p <= n):
if (prime[p] == True):
for i in range(p * 2, n+1, p):
prime[i] = False
p += 1
for p in range(2, n):
if not prime[p]:
#this is my change
if p == sum(k for k in range(1,p//2+1) if p%k == 0):
yield p
a = SieveOfEratosthenes(j)
b = next(a)
print(b)
try:
while b < j:
b = next(a)
print(b)
except StopIteration:
print("Done")
These work in theory, but I can't get it to work in a "reasonable" amount of time.
Hopefully these will help until someone can post a more efficient solution.
Even if you fix your code, it's the wrong approach for looking for perfect numbers - you're not likely to find more than the first four, and certainly not perfect numbers up to 100,000,000,000,000.
A better approach would be to search for Mersenne primes using a Lucas-Lehmer primality test and when you find one, compute its companion perfect number. This doesn't take much code and will easily eclipse your current approach.

Prime factorization: doesn't work with large numbers?

I'm trying to find the largest prime factor for a number. The code runs correctly on IDLE when used with smaller numbers, but doesn't seem to print anything to the screen at all when I assign a larger number like 600851475143 to n. Why?
def isPrime(n):
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
I'm running Python 3.3, by the way.
==============================================================================
Thanks everyone!
I fixed my original code as follows:
def isPrime(n):
for i in range(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
if i == n:
break
n = n / i
print("The largest prime factor is", largest)
Like nakedfanatic said, their code runs faster, and I edited it slightly:
largest = 0
n = 600851475143
i = 2
while True:
if n % i == 0:
largest = i
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", largest)
There are several areas of optimization:
all factorization only needs to got up to sqrt(n) (inclusive)
convert isPrime() to a table lookup
Initialize a lookup table using n, then you compute all primes < sqrt(n) only once and loop through them.
As comments pointed out, this takes up large memory space. We can use bit flag to cut the memory requirement to 1/8, and we can cut it by a further half if we skip all the even numbers (then have to test if n is even separately). But that may still be daunting for LARGE n.
(if using current code) return early in isPrime() (by #justhalf)
loop backwards (from sqrt(n) to 2) when looking up the largest factor
return early if the quotient is 1 after dividing by a factor (by #justhalf)
This post (suggested by #prashant) contains more complicated algorithm (making my suggestion very naive ><):
Fastest way to list all primes below N
... (edits are welcome)
It's because you keep trying even if n is already 1.
This code will help you to see the problem:
def isPrime(n):
for i in xrange(2,n-1):
if n % i == 0:
return False
return True
largest = 0
n = 600851475143
for i in xrange(2,n-1):
print 'Checking whether %d divides %d' % (i,n)
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
print("The largest prime factor is", largest)
which will produce:
...
Checking whether 6857 divides 6857
Checking whether 6858 divides 1
Checking whether 6859 divides 1
Checking whether 6860 divides 1
Checking whether 6861 divides 1
Checking whether 6862 divides 1
Checking whether 6863 divides 1
Checking whether 6864 divides 1
Checking whether 6865 divides 1
Checking whether 6866 divides 1
Checking whether 6867 divides 1
Checking whether 6868 divides 1
Checking whether 6869 divides 1
Checking whether 6870 divides 1
Checking whether 6871 divides 1
Checking whether 6872 divides 1
Checking whether 6873 divides 1
...
You should break the loop when n becomes 1, so that it won't do unnecessary checking
n = n / i
if n==1:
break
continue
And anyway, your code might be improved by a lot, haha, see others' suggestions.
Most likely, your code isn't terminating with large n, simply because it takes so long to run through the loop.
Your code is running in O(n²) time, which means it will quickly become unreasonably slow as the size of n increases. That is why your algorithm works for small values, but hangs for large values.
This code does the same thing in O(n) time without doing any prime checking at all, and returns a result instantly:
prime_factors = []
n = 600851475143
i = 2
while True:
if n % i == 0:
prime_factors.append(i)
if n == i:
# finished
break
n = n / i
else:
i += 1
print("The largest prime factor is", prime_factors[-1])
More difficult problems may require a different algorithm.
Check this question out: Fastest way to list all primes below N
Your code looks okay, but could take a long time for a large n. Leveraging math can enable you to do this problem orders of magnitude faster.
On that link, I recommend rwh_primes1 for a pure python solution, and primesfrom3to as one that uses numpy. Both of those implementations are fairly short, relatively clear, and do basically the same thing. Those code snippets are written in Python 2, so a translation might look like this:
def rwh_primes1(n):
sieve = [True] * (n//2)
for i in range(3, int(n**0.5)+1,2):
if sieve[i//2]:
sieve[i*i//2::i] = [False] * ((n-i*i-1)//(2*i)+1)
return [2] + [2*i+1 for i in range(1,n//2) if sieve[i]]
isPrime = True
for i in range(2,n-1):
if n % i == 0:
isPrime = False
return isPrime
This loop always exits the first iteration due to the unconditional return. Try:
for i in range(2,n-1):
if n % i == 0:
return False
return True
Also the upper bound n-1 can be reduced to sqrt(n)+1.
Another aspect of your code which may be slowing it down is the second half of your code
largest = 0
n = 600851475143
for i in range(2,n-1):
if isPrime(i) and n % i == 0:
largest = i
n = n / i
continue
Specifically the statement
if isPrime(i) and n % i == 0:
Per the documentation, the second condition is only evaluated if the first one is True. In your case it would make more sense to reverse the conditions so that computationally les expensive division is performed always and the more expensive isPrime() is only called for the actual factors
largest = 0
n = 600851475143
for i in range(2,n-1):
if n % i == 0 and isPrime(i):
largest = i
n = n / i
if n == 1:
break

Calculating prime numbers

I am now doing the MIT opencourse thing, and already the second assignment, I feel it has left me out in the cold. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/pset1a.pdf
The specifics of it, are to write something that can calculate the 1000th prime number. We only know about the print, ==, =, 1=,if, else, elif, while, %, -,+,*,/, commands I think. We also don't yet know about importing libraries.
My Idea of how it would work is to take an odd number and try to divide it by, 3,4,5,6,7,8,9 and if %n !=0, then add a number to NumberofPrimes variable starting with 11 as the base of the tests, and assigning it a base value of 4 at the base of NumberofPrimes, though I don't know if that is even right, because I wouldn't know how to display the 1000th prime number.
Am I close?
The latest incarnation of it is as follows:
##calculate the 1000th prime number
potprime = 3
numberofprime = 1
cycle = if potprime%3 = 0:
break
if potpimre%4 = 0:
break
if potprime%5 = 0:
break
if potprime%6 = 0:
break
if potprime%7 = 0:
break
if potprime%8 = 0:
break
if potprime%9 = 0:
break
numberofprime + 1
potprime + 1
if potprime%2 == 0:
potprime = potprime + 1
if potprime != 0:
cycle
Where exactly am I going wrong? Walk me through it step by step. I really want to learn it, though I feel like I am just being left out in the cold here.
At this point, it would be more beneficial for me to see how a proper one could be done rather than doing this. I have been working for 3 hours and have gotten nowhere with it. If anybody has a solution, I would be more than happy to look at it and try to learn from that.
Looks like I am late
It is quite straight forward that if a number is not divisible by any prime number, then that number is itself a prime number. You can use this fact to minimize number of divisions.
For that you need to maintain a list of prime numbers. And for each number only try to divide with prime numbers already in the list. To optimize further it you can discard all prime numbers more than square root of the number to be tested. You will need to import sqrt() function for that.
For example, if you test on 1001, try to test with 3, 5, 7, 11, 13, 17, 19, 23, 29 and 31. That should be enough. Also never try to find out if an even number is prime. So basically if you test an odd number n, then after that test next number: (n + 2)
Have tested the below code. The 1000th prime number is 7919. Not a big number!!
Code may be like:
from math import sqrt
primeList = [2]
num = 3
isPrime = 1
while len(primeList) < 1000:
sqrtNum = sqrt(num)
# test by dividing with only prime numbers
for primeNumber in primeList:
# skip testing with prime numbers greater than square root of number
if num % primeNumber == 0:
isPrime = 0
break
if primeNumber > sqrtNum:
break
if isPrime == 1:
primeList.append(num)
else:
isPrime = 1
#skip even numbers
num += 2
# print 1000th prime number
print primeList[999]
The following code is gross, but since 1000 is indeed a small index, it solves your problem in a fraction of a second (and it uses only the primitives you are supposed to know so far):
primesFound = 0
number = 1
while primesFound < 1000:
number = number + 1 # start from 2
# test for primality
divisor = 2
numberIsPrime = True
while divisor*divisor <= number: # while divisor <= sqrt(number)
if number % divisor == 0:
numberIsPrime = False
break
divisor = divisor + 1
# found one?
if numberIsPrime:
primesFound = primesFound + 1
print number
You can test the solution here.
Now you should find a more efficient solution, optimize and maybe go for the 1000000-th prime...
For one thing, I'm pretty sure that in Python, if you want to have an if statement that tests whether or not A = B, you need to use the == operator, rather then the =.
For another thing, your algorithm would consider the number 143 to be prime, even though 143 = 11 * 13
You need keep track of all the prime numbers that you have already computed - add them to an array. Use that array to determine whether or not a new number that you are testing is prime.
It seems to me that you are jumping into the deep-end after deciding the kiddy-pool is too deep. The prime number project will be assignment 2 or 3 in most beginning programming classes, just after basic syntax is covered. Rather than help you with the algorithm (there are many good ones out there) I'm going to suggest that you attempt to learn syntax with the python shell before you write long programs, since debugging a line is easier than debugging an entire program. Here is what you wrote in a way that will actually run:
count = 4
n = 10 #I'm starting you at 10 because your method
#says that 2, 3, 5, and 7 are not prime
d = [2, 3, 4, 5, 6, 7, 8, 9] #a list containing the ints you were dividing by
def cycle(n): #This is how you define a function
for i in d: #i will be each value in the list d
if not n%i: #this is equal to if n%i == 0
return 0 #not prime (well, according to this anyway)
return 1 #prime
while count < 1000:
count += cycle(n) #adds the return from cycle to count
n += 1
print n - 1
The answer is still incorrect because that is not how to test for a prime. But knowing a little syntax would at least get you that wrong answer, which is better than a lot of tracebacks.
(Also, I realize lists, for loops, and functions were not in the list of things you say you know.)
Your code for this answer can be condensed merely to this:
prime_count = 1
start_number = 2
number_to_check = 2
while prime_count <= 1000:
result = number_to_check % start_number
if result > 0:
start_number +=1
elif result == 0:
if start_number == number_to_check:
print (number_to_check)
number_to_check +=1
prime_count +=1
start_number =2
else:
number_to_check +=1
start_number = 2
To answer your subsequent question, 'How do I keep track of all the prime numbers?
One way of doing this is to make a list.
primeList = [] # initializes a list
Then, each time you test a number for whether it is prime or not, add that number to primeList
You can do this by using the 'append' function.
primeList.append( potprime ) # adds each prime number to that list
Then you will see the list filling up with numbers so after the first three primes it looks like this:
>>> primeList
[11, 13, 17]
Your math is failing you. A prime number is a number that has 2 divisors: 1 and itself. You are not testing the numbers for primality.
I am very late on this but maybe my answer will be of use to someone. I am doing the same open course at MIT and this is the solution I came up with. It returns the correct 1000th prime and the correct 100,000th prime and various others in between that I have tested. I think this is a correct solution (not the most efficient I am sure but a working solution I think).
#Initialise some variables
candidate = 1
prime_counter = 1
while prime_counter < 1000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
print "The 1000th prime is: " + str(candidate)
While I was at it I went on and did the second part of the assignment. The question is posed as follows:
"There is a cute result from number theory that states that for sufficiently large n the product of the primes less than n is less than or equal to e^n and that as n grows, this becomes a tight bound (that is, the ratio of the product of the primes to e^n gets close to 1 as n grows).
Computing a product of a large number of prime numbers can result in a very large number,
which can potentially cause problems with our computation. (We will be talking about how
computers deal with numbers a bit later in the term.) So we can convert the product of a set of primes into a sum of the logarithms of the primes by applying logarithms to both parts of this conjecture. In this case, the conjecture above reduces to the claim that the sum of the
logarithms of all the primes less than n is less than n, and that as n grows, the ratio of this sum to n gets close to 1."
Here is my solution. I print the result for every 1,000th prime up to the 10,000th prime.
from math import *
#Initialise some variables
candidate = 1
prime_counter = 1
sum_logs = log(2)
while prime_counter < 10000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
# If the number is prime add its log to the sum of logs.
sum_logs = sum_logs + log(candidate)
if prime_counter%1000 == 0:
# For every 1000th prime print the result.
print sum_logs," ",candidate," ",sum_logs/candidate
print "The 10000th prime is: " + str(candidate)
Cheers,
Adrian
I came up with this solution in my interview, but I didn't get the job :( It has about 1/100 less iterations than the solution above:
from math import *
MAX_IDX=1000
MAX_IDX-=1
num_iter=0
l_pirme_list=[3]
candidate=l_pirme_list[0]
prime_counter=1
while prime_counter < MAX_IDX:
candidate+=2
#Cut the binary number in half. This is quite faster than sqrt()
bin_candidate=format(candidate, "2b")
max_prime_search=int(bin_candidate[:len(bin_candidate)/2+1],2)+1
# max_prime_search=sqrt(candidate)+1
candidate_is_prime=1
for prime_item in l_pirme_list:
num_iter+=1
if candidate % prime_item==0:
candidate_is_prime=0
break
elif prime_item > max_prime_search:
candidate_is_prime=1
break
if candidate_is_prime:
prime_counter+=1
l_pirme_list.append(candidate)
l_pirme_list.insert(0,2)
print "number iterations=", num_iter
print l_pirme_list[MAX_IDX]

Categories