Python "OverflowError" [duplicate] - python

This question already has answers here:
`xrange(2**100)` -> OverflowError: long int too large to convert to int
(5 answers)
Closed 13 days ago.
I am just starting to learn to code in Python. I am trying to write some code to answer this Project Euler Question:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
My program works with the test case of 13195, but when I try to enter 600851475143, I get the error: "OverflowError: range() results has too many items"
Does anyone know how I can fix this?
Here is my code:
class Euler3:
"A class to find the largest prime factor of a given number"
n = 600851475143
primeFactors = []
for i in range(2,n):
if (n%i ==0):
primeFactors.append(i)
n = n/i
i = i -1 #reset i
print primeFactors
Any help or suggestions would be much appreciated!

The range function creates a list and tries to store it in memory. Creating a list many numbers long is what's causing the OverflowError. You can use xrange instead to get a generator which produces the numbers on demand.
That said, I think you'll find that your algorithm is way too slow for calculating large primes. There are a lot of prime number algorithms, but I might suggest checking out the Sieve of Eratosthenes as a starting point.
EDIT: Properly xrange actually doesn't return a generator, but an xrange object which behaves a lot like a generator. I'm not sure if you care, but it was bugging me that i wasn't precise!

I'm guessing you're using python 2 and not python 3 -- range(2,n) actually constructs a list! You don't have enough memory to store 600 billion numbers! xrange should be fine, though.
Also, your idea of i=i-1 doesn't work. For loops don't work like C, and that hack only works in C-style loops. The for loop iterates over range(2,n). If i gets the value 5 at once iteration, then no matter what you do to i, it still gets 6 the next time through.
Also, the list range(2,n) is constructed when you enter the loop. So when you modify n, that doesn't change anything.
You're going to have to rethink your logic a bit.
(if you don't believe me, try using 175 as a test case)
As a last comment, you should probably get in the habit of using the special integer division: n = n // i. Although / and // work the same in python 2, that is really deprecated behavior, and they don't work the same in python 3, where / will give you a floating point number.

You can fix the problem by using xrange instead of range
Your next problem will be that the program takes way too long to run because you need to break out of the loop under some condition
A better way to deal with repeat factors is to replace the if with a while
while (n%i ==0):
primeFactors.append(i)
n = n/i

n = 600851475143
primeFactors = []
for i in range(2,n):
i think you can optimize the function by noticing that
for i in range(2,n):
you can replace
range(2,n)
by
range(2,int(sqrt(n))+2)
because, you can see wiki...

This is the best way to find primes that I've found so far:
def isprime(n):
#make sure n is a positive integer
n = abs(int(n))
#0 and 1 are not primes
if n < 2:
return False
#2 is the only even prime number
if n == 2:
return True
#all other even numbers are not primes
if not n & 1:
return False
#range starts with 3 and only needs to go up to the square root of n
#for all odd numbers
for x in range (3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True #if it makes it through all the catches, it is a prime

This took me about 5 secs to get the answer.
import math
def is_prime_number(x):
for i in range(int(math.sqrt(x)), 2, -1):
if x % i == 0:
return False
return True
def next_prime_number(number):
#Returns the next prime number.
if number % 2 == 0 and number != 2:
number += 1
while not is_prime_number(number):
number += 2
return number
num = 600851475143
i = 2
while (i < long(math.sqrt(num) / 2)):
if num % i == 0:
largest = i
print largest
i = next_prime_number(i + 1)

xrange won't probably help you(or it may!),but the key thing here is to reliaze that you don't need to find the prime numbers up till 600851475143 or the factors of 600851475143,but it's prime factors,so...
Use the good old prime factorization method ,like so:
A=600851475143
n=2
fac=[]
while(n<=int(A)):
B=1
while(A%n==0):
B=0
A=A/n
if(B==0):
fac.append(n)
n=n+1
print max(fac)
This will return the argest prime factor almost instantly

I was battling with this Python "OverflowError", as well, working on this project. It was driving me nuts trying to come up with a combination that worked.
However, I did discover a clever, at least I think so :), way to do it.
Here is my code for this problem.
def IsNumberPrime(n):
bounds = int(math.sqrt(n))
for number in xrange(2,bounds+2):
if n % number == 0:
return False
return True
def GetListOfPrimeFactors(n):
primes = []
factors = GetListOfFactors(n)
if n % 2 == 0:
primes.append(2)
for entries in factors:
if IsNumberPrime(entries):
primes.append(entries)
return primes
GetListOfPrimeFactors(600851475143)
def GetListOfFactors(n):
factors = []
bounds = int(math.sqrt(n))
startNo = 2
while startNo <= bounds:
if n % startNo == 0:
factors.append(startNo)
startNo += 1
return factors
What I did was take the factors of the number entered and enter them into a list "factors". After that, I take the list of factors and determine which ones are primes and store them into a list, which is printed.
I hope this helps
-- Mike

Related

Prime checker including non primes

I am trying to solve Project Euler number 7.
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?
First thing that came into my mind was using length of list. This was very ineffective solution as it took over a minute. This is the used code.
def ch7():
primes = []
x = 2
while len(primes) != 10001:
for i in range(2, x):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is: 104743.
This works well but I wanted to reach faster solution. Therefore I did a bit of research and found out that in order to know if a number is a prime, we need to test whether it is divisible by any number up to its square root e.g. in order to know if 100 is a prime we dont need to divide it by every number up to 100, but only up to 10.
When I implemented this finding weird thing happened. The algorithm included some non primes. To be exact 66 of them. This is the adjusted code:
import math
primes = []
def ch7():
x = 2
while len(primes) != 10001:
for i in range(2, math.ceil(math.sqrt(x))):
if x % i == 0:
break
else:
primes.append(x)
x += 1
print(primes[-1])
ch7()
# Output is 104009
This solution takes under a second but it includes some non primes. I used math.ceil() in order to get int instead of float but I figured it should not be a problem since it still tests by every int up to square root of x.
Thank you for any suggestions.
Your solution generates a list of primes, but doens't use that list for anything but extracting the last element. We can toss that list, and cut the time of the code in half by treating 2 as a special case, and only testing odd numbers:
def ch7(limit=10001): # assume limit is >= 1
prime = 2
number = 3
count = 1
while count < limit:
for divisor in range(3, int(number ** 0.5) + 1, 2):
if number % divisor == 0:
break
else: # no break
prime = number
count += 1
number += 2
return prime
print(ch7())
But if you're going to collect a list of primes, you can use that list to get even more speed out of the program (about 10% for the test limits in use) by using those primes as divisors instead of odd numbers:
def ch7(limit=10001): # assume limit is >= 1
primes = [2]
number = 3
while len(primes) < limit:
for prime in primes:
if prime * prime > number: # look no further
primes.append(number)
break
if number % prime == 0: # composite
break
else: # may never be needed but prime gaps can be arbitrarily large
primes.append(number)
number += 2
return primes[-1]
print(ch7())
BTW, your second solution, even with the + 1 fix you mention in the comments, comes up with one prime beyond the correct answer. This is due to the way your code (mis)handles the prime 2.

Project Euler #10 (Python)

Why is my algorithm for finding the sum of all prime numbers below 2 million so slow?
I'm a fairly beginner programmer and this is what I came up with for finding the solution:
import time
sum = 2
start = time.time()
for number in range(3, 2000000):
prime = True
for x in range(2, number):
if number % x == 0:
prime = False
if prime:
sum += number
print "Sum =", sum
end = time.time() - start
print "Runtime =", end
Can someone please help me out?
Thanks!
Your algorithm uses trial division, which is very slow. A better algorithm uses the Sieve of Eratosthenes:
def sumPrimes(n):
sum, sieve = 0, [True] * n
for p in range(2, n):
if sieve[p]:
sum += p
for i in range(p*p, n, p):
sieve[i] = False
return sum
print sumPrimes(2000000)
That should run in less than a second. If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.
There are many optimisations that you could do (and should do since you will need prime generation for many of the problems in project Euler, so having a fast implementation simplifies things later on).
Take a look at the sieve of Atkin (and related sieves) (http://en.wikipedia.org/wiki/Sieve_of_Atkin) to get an understanding of how prime generation can be speeded up over brute force (algorithmically that is).
Then take a look at the awesome answer to this S.O.-post (Fastest way to list all primes below N) that clocks a number of prime generation algorithms/implementations.
Nobody pointed this out, but using range in Python 2.x is very slow. Use xrange instaed, in this case this should give you a huge performance advantage.
See this question.
Also, you don't have to loop until the number you check, checking until round(sqrt(n)) + 1 is sufficient. (If the number greater than its square divides it, there's a number smaller than the square that you must have already noticed.)
You need to use prime sieve check out eratostheneses sieve and try to implement it in code.
Trial division is very inefficient for finding primes because it has complexity n square, the running time grows very fast. This task is meant to teach you how to find something better.
First off, you're looping over too many numbers. You don't need to check if EVERY number less than a given number is a divisor to check if a number is prime (I'll let you figure out why this is yourself). You are running hundreds of billions of loops, where hundreds of millions will do.
Something like this works faster, but is by no means optimal:
value=2
for i in range(3, 2000000):
prime=True
if i%2 != 0:
for j in range(3, int(round(sqrt(i)+1)),2):
if i % j==0:
prime=False
else:
prime=False
if prime==True:
value+=i
print value
First of all, I think you can split your code by defining a function. However, there is a drawback of using a regular function in this case because every time a normal function return a value, the next call to the function will execute the complete code inside the function again. Since you are iterating 2 million times, it would be better to:
Have a function that gives you the next prime number and provisionally returns the control to the caller. Such functions are known as GENERATORS.
To define a generator function just use the yield command instead of return.
When you use generators , it is like knowing that the function will be called again and when it happens the execution inside the function continues right after the yield instruction instead of going over the whole function again.
The advantage of this approach is that on the long run of an iterator you avoid the consumption all of the system's memory.
I recommend you to have a look at this article about generators in python. It provides a more extensive explanation for this example.
The solution would be something like this:
import math
# Check if a number is prime
def is_prime(number):
if number > 1:
if number == 2:
return True
if number % 2 == 0:
return False
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
# Get the next after a given number
def get_primes(number):
while True:
if is_prime(number):
yield number
# Next call to the function will continue here!
number += 1
# Get the sum of all prime numbers under a number
def sum_primes_under(limit):
total = 2
for next_prime in get_primes(3):
if next_prime < limit:
total += next_prime
else:
print(total)
return
# Call the function
sum_primes_under(2000000)
This question gives output quite very fast when you use sieve of eratosthenes Link to it. You can make it even more faster with a little modification like iterating the whole 2 million numbers just half times by considering only the odd numbers. This way you can save lots of time.
n = 2000000
ar = [False for x in range(n)]
sum = 2
def mul(a):
i = 2;p = i*a
while (p < n):
ar[p] = 1
++i
p = i*a
while (x < n):
if(ar[x] == 0):
sum += x;mul(x)
x += 2
print (sum)
Here you can see the same algorithm in c++:-
#include<bits/stdc++.h>
using namespace std;
const int n = 2000000;
bool ar[n];
void mul(int a)
{
int i = 2;int p = i*a;
while(p < n)
{
ar[p] = 1;
++i;p = i*a;
}
}
long long sieve()
{
long long sum = 2;
for(int i = 3;i < n;i += 2)
{
if(ar[i] == 0)
sum += i,mul(i);
}
return sum;
}
int main()
{
cout<<sieve();
return 0;
}
C++ works around 10 times faster than python anyways and for this algorithm too.
sum = 2
def isPrime(n):
if n % 2 == 0: return False
for i in range(3, int(n**0.5)+1, 2):
if n % i == 0: return False
return True
if __name__ == "__main__":
n = 1
while n < 2000000:
n += 2
if isPrime(n):sum += n
print sum
import time
start = time.time()
def is_prime(num):
prime = True
for i in range(2,int(num**0.5)+1):
if num % i == 0:
prime = False
break
return prime
sum_prime = 0
for i in range(2,2000000):
if is_prime(i):
sum_prime += i
print("sum: ",sum_prime)
elapsed = (time.time() - start)
print("This code took: " + str(elapsed) + " seconds")

Euler Project #3 in Python

I'm trying to solve the Project Euler problem 3 in Python:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
I know my program is inefficient and oversized, but I just wanted to know why doesn't it work?
Here's the code:
def check(z):
# checks if the given integer is prime
for i in range(2, z):
if z % i == 0:
return False
break
i = i+1
return True
def primegen(y):
# generates a list of prime integers in the given range
tab = []
while y >= 2:
if check(y) == True:
tab.append(y)
i = i-1
def mainfuntion(x):
# main function; prints the largest prime factor of the given integer
primegen(x)
for i in range(len(tab)):
if x % tab[i] == 0:
print tab[i]
break
mainfuntion(600851475143)
And here's the error:
for i in range(2, z):
OverflowError: range() result has too many items
The reason is that a list in Python is limited to 536,870,912 elements (see How Big can a Python Array Get?) and when you create the range in your example, the number of elements exceeds that number, causing the error.
The fun of Project Euler is figuring out the stuff on your own (which I know you're doing :) ), so I will give one very small hint that will bypass that error. Think about what a factor of a number is - you know that it is impossible for 600851475142 to be a factor of 600851475143. Therefore you wouldn't have to check all the way up to that number. Following that logic, is there a way you can significantly reduce the range that you check? If you do a bit of research into the properties of prime factors, you may find something interesting :)
This is the code that I used!!
n = 600851475143
i = 2
while i * i < n:
while n % i == 0:
n = n / i
i = i + 1
print n
-M1K3
#seamonkey8: Your code can be improved. You can increase it by 2 rather than one. It makes a speed difference for really high numbers:
n,i = 6008514751231312143,2
while i*i <= n:
if n%i == 0:
n //= i
else:
i+=[1,2][i>2]

Python prime number list wrong?

I've tried with several different methods to get the 10001 prime number.
def isPrime(value):
if ((2**value)-2)%value==0:
return True
def nthPrime(n):
count = 0
value = 1
while count < n:
value += 1
if isPrime(value):
count += 1
return value
When 10001 is the argument this returns 103903. When I'm expecting 104743.
I've tried:
primes = []
for i in range(2,105000):
if ((2**i) - 2) % i == 0:
primes.append(i)
print primes[10001] ---> 103903
I believe your prime sieve is wrong. Try using an isPrime function that takes that number mod each lesser prime. If any of these are 0 then the number is composite (not prime). To the best of my knowledge there is no single comparison that will tell you if a number is prime, as your isPrime function assumes.
Is this for Project Euler? It does seem familiar to me.
Your isPrime function is wrong, like TEOUltimus said, there is no one way to tell if a number is prime.
Simple Prime Generator in Python
This pretty much answers your question i guess.
You can make a function to generate primes, this might be slow but it will work.
Here's my function to do so :
def PrimesSieve(limit):
np=set()
p=[2]
for i in xrange(1,limit+1,2):
if i == 1: continue
if {i} & np: continue
beg=2 if i % 2 == 0 else 0
for j in xrange(beg,int(limit)+1,i):
np.add(j)
p.append(i)
return p

Program to factorize a number into two smaller prime numbers

I have a very big number, and I want to make a program, that finds two prime numbers, that will give the original number, if multiplied.
Ex.
Original_number = 299
// The program should get these two numbers:
q = 13
p = 23
The program runs fine at the start, but at a certain point, it just stops, and I'm not sure what is wrong.
The code:
import time
import math
def main():
time1 = time.clock()
q = int(0)
p = int(0)
finalnumber = int(377)
print("in main \n")
print("q = ", q)
print("\n p = ", p)
gotResult = 0
while(gotResult == 0):
p = GetNextPrime(p)
if(p >= finalnumber):
q = GetNextPrime(q)
p = q
p = GetNextPrime(p)
if(q * p == finalnumber):
gotResult == 1
break
print("q = ", q)
print("\n p = ", p)
time2 = time.clock()
ElapsedTime = time2 - time1
print("Elapsed time: ", ElapsedTime)
def GetNextPrime(prime):
print("in GetNextPrime \n")
isPrime = 0
while(isPrime == 0):
prime = prime + 1
if(IsPrime(prime)== 1):
isPrime = 1
return prime
def IsPrime(prime):
print("in IsPrime \n")
isPrime = 0
i = 2
while(i <= math.sqrt(prime)):
if(i % 2 == 0):
i = i+1
if(prime % i == 0):
isPrime = 1
break
return isPrime
#start of program here
main()
I have written the program in python, and I know it probably isn't good, because I'm new to python.(I have been programming C++, and I'm not even good at it)
But I hope you can help me find the problem :)
ps. What is the maximum size of the original number? How many ciphers can it have?
Just factorize a number. You'll get a list of prime factors. If the list contains exactly two numbers, and the numbers are good for your purposes, you won. Else try another number.
But the approach above is quite wasteful. I'd rather take a list of primes, generate all pairs of it and multiply. The result would be a list of numbers that, well, can only be factorized into 2 primes. Like this:
some_primes = [2, 3, 5, 7, 11] # you can generate a better list
my_numbers = [x*y for x in some_primes for y in some_primes]
A simple approach is trial division:
import math
def factors(number):
return [(x, number / x) for x in range(int(math.sqrt(number)))[2:] if not number % x]
Then factors(299) returns [(13,23)]
There are problems with this method for large numbers:
Large numbers may exceed the python integer limit (found in sys.maxint). A 64-bit machine will be limited to 18 decimal digits.
Factoring large numbers is a hard problem, and an open research question. Trial division is about as brute force as it comes, but it will work for smaller numbers. Otherwise, you'll quickly need a more sophisticated algorithm. See wikipedia for a discussion.
If you're going to brute-force numerical problems, python is the wrong language. Identical algorithms will run faster in a compiled language like C++.
isPrime is wrong. You return 1 when the number is not prime. Also you never test if the number can be divided by 2. I didn't look any further than that.
Protip: Python is not C. There is True, False and you don't need all the brackets in if, while.
You should really test every function you write, not the whole program - that tells you nothing about where the bugs are.
In addition to Jochel Ritzel's and DSM's answers, the logic in main() while loop fails to account for cases when the number is not a product of two primes (then it will go into infinite loop).
Also, if you expect to factor really large numbers (say more than 20-30 digits), your approach is probably too slow. You should use Erastothenes sieve at minimum to generate a large enough list of primes in advance if you want to get acceptable results.
There are (pretty sophisticated) algoritms to deal with larger cases, but in general, this is a difficult problem and the solution to it scales very badly with number of digits.
In the following logic:
while(i <= math.sqrt(prime)):
if(i % 2 == 0):
i = i+1
if(prime % i == 0):
isPrime = 1
break
If i is odd and prime isn't divisible by it, it'll loop forever, and here it gets stuck on 3. [The other obvious problem has already been pointed out.]

Categories

Resources