Fast Prime Generator besides Sieve - python

I recently made this bit of code, but wonder if there is a faster way to find primes (not the Sieve; I'm still trying to make that). Any advice? I'm using Python and I'm rather new to it.
def isPrime(input):
current = 0
while current < repetitions:
current = current + 2
if int(input) % current == 0:
if not current == input:
return "Not prime."
else:
return "Prime"
else:
print current
return "Prime"
i = 1
primes = []
while len(primes) < 10001:
repetitions = int(i)-1
val = isPrime(i)
if val == "Prime":
primes.append(i)
i = i + 2
print primes[10000]

here is a function that detect if x is prime or not
def is_prime(x):
if x == 1 or x==0:
return False
elif x == 2:
return True
if x%2 == 0:
return False
for i in range(3, int((x**0.5)+1), 2):
if x%i == 0:
return False
return True
and another implementation that print prime numbers < n
def prime_range(n):
print(2)
for x in range(3, n, 2):
for i in range(3, int((x**0.5)+1), 2):
if x%i == 0:
break
else:
print(x)
hope it helps !

If you are not using a sieve, then the next best are probably wheel methods. A 2-wheel checks for 2 and odd numbers thereafter. A 6-wheel checks for 2, 3 and numbers of the form (6n +/- 1), that is numbers with no factors of 2 or 3. The answer from taoufik A above is a 2-wheel.
I cannot write Python, so here is the pseudocode for a 6-wheel implementation:
function isPrime(x) returns boolean
if (x <= 1) then return false
// A 6-wheel needs separate checks for 2 and 3.
if (x MOD 2 == 0) then return x == 2
if (x MOD 3 == 0) then return x == 3
// Run the wheel for 5, 7, 11, 13, ...
step <- 4
limit <- sqrt(x)
for (i <- 5; i <= limit; i <- i + step) do
if (x MOD i == 0) then return false
step <- (6 - step) // Alternate steps of 2 and 4.
end for
return true
end function
I leave it to you to convert that into Python.

As in
n = 10000
for p in range(2, n+1):
for i in range(2, p):
if p % i == 0:
break
else:
print p
print 'Done'
?

Related

Finding the sum of prime numbers between m and n (m and n included in the sum)

def isPrime(n, i):
if i == n-1:
return ("True")
elif n%i == 0:
return ("False")
else:
return isPrime(n, i+1)
def sumOfPrime(m,n):
if m > 0 and n > 0 and m <= n:
if isPrime(m,2)==True:
temp = temp + m
return temp
else:
return (sumOfPrime(m+1,n))
else:
return temp
how can I fix the error "UnboundLocalError: local variable 'temp' referenced before assignment" without using a global variable
I reviewed your code, and this is my proposal:
def isPrime(n, i=None):
if i is None:
i = n - 1
while i >= 2:
if n % i == 0:
return False
else:
return isPrime(n, i-1)
else:
return True
def sumOfPrime(m, n):
sum = 0
for value in range(m, n+1):
if isPrime(value):
sum = sum + value
return sum
# --- test ---
result = sumOfPrime(1, 9)
print (result) # <-- prints 18
If the difference between m and n is quite high, then it is recommended that you use some type of sieve, to filter primes out in a given range. Otherwise, iterating over numbers from m to n and checking if the number is prime, it is going to be expensive for large m and n.
def is_prime(n):
if n <= 2:
return n > 1
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
def prime_range_sum(m, n):
return sum(i for i in range(m, n + 1) if is_prime(i))
print(prime_range_sum(1, 9))
# prints 17
Here's my version, which I kept as close as possible to the original, while fixing some errors and making some adjustments.
def isPrime(n, i=2): # since you always use 2, just make it default
if i == n-1:
return True # return a boolean True instead of a string
elif n%i == 0:
return False # return a boolean False instead of a string
else:
return isPrime(n, i+1)
def sumOfPrime(m,n,total=0): # we will need to carry the total around, make default to 0
if 0 < m <= n: # we can simplify this complex condition
if isPrime(m):
total += m # if it's prime, increase the total...
return sumOfPrime(m+1, n, total) # and pass it to the next recursion
return total # if this is the last recursion, return total
# Example run
total = sumOfPrime(10,45)
print(total) # prints 264

Having trouble with implementeing the Miller-Rabin compositeness in Python

I'm not sure if this is the right place to post this question so if it isn't let me know! I'm trying to implement the Miller Rabin test in python. The test is to find the first composite number that is a witness to N, an odd number. My code works for numbers that are somewhat smaller in length but stops working when I enter a huge number. (The "challenge" wants to find the witness of N := 14779897919793955962530084256322859998604150108176966387469447864639173396414229372284183833167 in which my code returns that it is prime when it isn't) The first part of the test is to convert N into the form 2^k + q, where q is a prime number.
Is there some limit with python that doesn't allow huge numbers for this?
Here is my code for that portion of the test.
def convertN(n): #this turns n into 2^x * q
placeholder = False
list = []
#this will be x in the equation
count = 1
while placeholder == False:
#x = result of division of 2^count
x = (n / (2**count))
#y tells if we can divide by 2 again or not
y = x%2
#if y != 0, it means that we cannot divide by 2, loop exits
if y != 0:
placeholder = True
list.append(count) #x
list.append(x) #q
else:
count += 1
#makes list to return
#print(list)
return list
The code for the actual test:
def test(N):
#if even return false
if N == 2 | N%2 == 0:
return "even"
#convert number to 2^k+q and put into said variables
n = N - 1
nArray = convertN(n)
k = nArray[0]
q = int(nArray[1])
#this is the upper limit a witness can be
limit = int(math.floor(2 * (math.log(N))**2))
#Checks when 2^q*k = 1 mod N
for a in range(2,limit):
modu = pow(a,q,N)
for i in range(k):
print(a,i,modu)
if i==0:
if modu == 1:
break
elif modu == -1:
break
elif i != 0:
if modu == 1:
#print(i)
return a
#instead of recalculating 2^q*k+1, can square old result and modN that.
modu = pow(modu,2,N)
Any feedback is appreciated!
I don't like unanswered questions so I decided to give a small update.
So as it turns out I was entering the wrong number from the start. Along with that my code should have tested not for when it equaled to 1 but if it equaled -1 from the 2nd part.
The fixed code for the checking
#Checks when 2^q*k = 1 mod N
for a in range(2,limit):
modu = pow(a,q,N)
witness = True #I couldn't think of a better way of doing this so I decided to go with a boolean value. So if any of values of -1 or 1 when i = 0 pop up, we know it's not a witness.
for i in range(k):
print(a,i,modu)
if i==0:
if modu == 1:
witness = False
break
elif modu == -1:
witness = False
break
#instead of recalculating 2^q*k+1, can square old result and modN that.
modu = pow(modu,2,N)
if(witness == True):
return a
Mei, i wrote a Miller Rabin Test in python, the Miller Rabin part is threaded so it's very fast, faster than sympy, for larger numbers:
import math
def strailing(N):
return N>>lars_last_powers_of_two_trailing(N)
def lars_last_powers_of_two_trailing(N):
""" This utilizes a bit trick to find the trailing zeros in a number
Finding the trailing number of zeros is simply a lookup for most
numbers and only in the case of 1 do you have to shift to find the
number of zeros, so there is no need to bit shift in 7 of 8 cases.
In those 7 cases, it's simply a lookup to find the amount of zeros.
"""
p,y=1,2
orign = N
N = N&15
if N == 1:
if ((orign -1) & (orign -2)) == 0: return orign.bit_length()-1
while orign&y == 0:
p+=1
y<<=1
return p
if N in [3, 7, 11, 15]: return 1
if N in [5, 13]: return 2
if N == 9: return 3
return 0
def primes_sieve2(limit):
a = [True] * limit
a[0] = a[1] = False
for (i, isprime) in enumerate(a):
if isprime:
yield i
for n in range(i*i, limit, i):
a[n] = False
def llinear_diophantinex(a, b, divmodx=1, x=1, y=0, offset=0, withstats=False, pow_mod_p2=False):
""" For the case we use here, using a
llinear_diophantinex(num, 1<<num.bit_length()) returns the
same result as a
pow(num, 1<<num.bit_length()-1, 1<<num.bit_length()). This
is 100 to 1000x times faster so we use this instead of a pow.
The extra code is worth it for the time savings.
"""
origa, origb = a, b
r=a
q = a//b
prevq=1
#k = powp2x(a)
if a == 1:
return 1
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}")
while r != 0:
prevr = r
a,r,b = b, b, r
q,r = divmod(a,b)
x, y = y, x - q * y
if withstats == True:
print(f"a = {a}, b = {b}, q = {q}, r = {r}, x = {x}, y = {y}")
y = 1 - origb*x // origa - 1
if withstats == True:
print(f"x = {x}, y = {y}")
x,y=y,x
modx = (-abs(x)*divmodx)%origb
if withstats == True:
print(f"x = {x}, y = {y}, modx = {modx}")
if pow_mod_p2==False:
return (x*divmodx)%origb, y, modx, (origa)%origb
else:
if x < 0: return (modx*divmodx)%origb
else: return (x*divmodx)%origb
def MillerRabin(arglist):
""" This is a standard MillerRabin Test, but refactored so it can be
used with multi threading, so you can run a pool of MillerRabin
tests at the same time.
"""
N = arglist[0]
primetest = arglist[1]
iterx = arglist[2]
powx = arglist[3]
withstats = arglist[4]
primetest = pow(primetest, powx, N)
if withstats == True:
print("first: ",primetest)
if primetest == 1 or primetest == N - 1:
return True
else:
for x in range(0, iterx-1):
primetest = pow(primetest, 2, N)
if withstats == True:
print("else: ", primetest)
if primetest == N - 1: return True
if primetest == 1: return False
return False
# For trial division, we setup this global variable to hold primes
# up to 1,000,000
SFACTORINT_PRIMES=list(primes_sieve2(100000))
# Uses MillerRabin in a unique algorithimically deterministic way and
# also uses multithreading so all MillerRabin Tests are performed at
# the same time, speeding up the isprime test by a factor of 5 or more.
# More k tests can be performed than 5, but in my testing i've found
# that's all you need.
def sfactorint_isprime(N, kn=5, trialdivision=True, withstats=False):
from multiprocessing import Pool
if N == 2:
return True
if N % 2 == 0:
return False
if N < 2:
return False
# Trial Division Factoring
if trialdivision == True:
for xx in SFACTORINT_PRIMES:
if N%xx == 0 and N != xx:
return False
iterx = lars_last_powers_of_two_trailing(N)
""" This k test is a deterministic algorithmic test builder instead of
using random numbers. The offset of k, from -2 to +2 produces pow
tests that fail or pass instead of having to use random numbers
and more iterations. All you need are those 5 numbers from k to
get a primality answer. I've tested this against all numbers in
https://oeis.org/A001262/b001262.txt and all fail, plus other
exhaustive testing comparing to other isprimes to confirm it's
accuracy.
"""
k = llinear_diophantinex(N, 1<<N.bit_length(), pow_mod_p2=True) - 1
t = N >> iterx
tests = []
if kn % 2 == 0: offset = 0
else: offset = 1
for ktest in range(-(kn//2), (kn//2)+offset):
tests.append(k+ktest)
for primetest in range(len(tests)):
if tests[primetest] >= N:
tests[primetest] %= N
arglist = []
for primetest in range(len(tests)):
if tests[primetest] >= 2:
arglist.append([N, tests[primetest], iterx, t, withstats])
with Pool(kn) as p:
s=p.map(MillerRabin, arglist)
if s.count(True) == len(arglist): return True
else: return False
sinn=14779897919793955962530084256322859998604150108176966387469447864639173396414229372284183833167
print(sfactorint_isprime(sinn))

Why does my boolean function sometimes return None?

Using Python 3.4. Have attempted to call function prime/2 that returns a boolean--always either True or False--from within an IF-statement. The function is expensive to run, so I want to call it only when I know it is needed, hence calling from within a decision point. The called function does not reliably return True/False. Sometimes the return is None, at which point the test fails. I use Python's IDLE and its debugger. I call primes(2, 5, []) and step through the code. When prime/2 reaches line elif n <= p while n = 5 and p = 5, the debugger shows that prime/2 returns True, as it should, but the line in primes/3 elif prime(m, 2) takes a value of None. And at that point my test fails. My code:
def primes(m, n, l): # the calling function
if m > n: # creates a list of primes from
print(l, end='\n') # m through n, inclusive
elif m < 2:
primes(2, n, l)
elif m == 2:
l.append(2)
primes(3, n, l)
elif m % 2 == 0:
primes(m + 1, n, l)
elif prime(m, 2): # calling the second function
l.append(m) # to test m for primality
primes(m + 2, n, l)
else:
primes(m + 2, n, l)
def prime(n, p): # the called function will return
if n < 2: # True if m is prime, False otherwise
return False
elif n < 4:
return True
elif n <= p:
return True
elif (n > 2) and (n % p == 0):
return False
elif p == 2:
prime(n, 3)
else:
prime(n, p + 2)
The error is in how you call prime() recursively. You need to explicitly return the value. Like this:
def prime(n, p): # the called function will return
if n < 2: # True if m is prime, False otherwise
return False
elif n < 4:
return True
elif n <= p:
return True
elif (n > 2) and (n % p == 0):
return False
elif p == 2:
return prime(n, 3) # <--- RETURN VALUE
return prime(n, p + 2) # <--- & RETURN VALUE

'IF' condition misbehaving

Here is a code that determines whether an input is PRIME number or not.
def is_prime(x):
for n in range(2, x - 1):
if x < 2 or x % n == 0:
return False
else:
return True
But the if condition inside the for loop doesn't work as expected. If x < 2, it should return false. So is_prime(1) should return false as 1 is less than 2. But the program returns True instead, which is not expected. On the other hand, if you put that if just outside the for loop like this, IT WORKS:
def is_prime(x):
if x < 2: return False
for n in range(2, x - 1):
if x % n == 0:
return False
else: return True
Why is this happening?
Over here,
for n in range(2, x - 1):
the for loop never runs if x == 1, then, you are essentially saying:
for n in range(2, 0):
which can't happen, so it just returns True from the else statement.
Your second function works because, as you said, the if statement is outside of the for loop
def is_prime(x):
if x < 9:
return x in {2, 3, 5, 7}
elif not (x % 2):
# even
return False
else:
upto = int(x ** 0.5) # test to sqrt(x)
# test divisibility by odd numbers
return all(x % div for div in range(3, upto+1, 2))

Generating large prime numbers in python

I can't seem to make random prime numbers using this code, please can someone help me?
def RandomPrime():
prime = False
while prime == False:
n = random.randint(10000, 100000)
if n % 2 != 0:
for x in range(3, int(n**0.5), 2):
if n % x ==0:
prime = False
else:
prime = True
return n
Imagine what happens if the last number in range(3, int(n**0.5), 2) is not an integer divisor of n:
if n % x ==0:
prime = False # not this
else:
prime = True # this
So even if all previous checks evaluated False, you call n a prime. The minimal change to your code to fix this is:
prime = prime and True # or 'prime &= True'
So if prime is already False, it remains False.
However, bear in mind that, for primality, if any of those checks is False n is not prime. You can use this and Python's and and all (which are evaluated lazily, i.e. don't keep checking once finding a False) to implement much more efficiently:
def rand_prime():
while True:
p = randint(10000, 100000)
if (r % 2 != 0 and
all(p % n != 0 for n in range(3, int(((p ** 0.5) + 1), 2))):
return p
For even better performance, note that randrange incorporates a step argument, just like range, so you can skip all of the even numbers (which definitely aren't prime!):
def rand_prime():
while True:
p = randrange(10001, 100000, 2)
if all(p % n != 0 for n in range(3, int((p ** 0.5) + 1), 2)):
return p
Note: sqrt(n) (from math) is, in my opinion, a little clearer to other, less-technical readers than n ** 0.5 (although it may or may not be more efficient).
Take a look to the tabs: The else should refer to the whole for loop, not to the iF
def RandomPrime():
prime = False
while prime == False:
n = random.randint(10000, 100000)
if n % 2 != 0:
for x in range(3, int(n**0.5), 2):
if n % x ==0:
break
else:
prime = True
return n
There're errors in your code:
Incorrect "else:"; you can't declare number being prime if a remainder is not 0;
All the remaiders should be non-zeros
int(n*0.5) should be int(n*0.5 + 1) to prevent round-up errors
The possible solution is
def RandomPrime():
while True:
n = random.randint(10000, 100000)
if n % 2 == 0:
continue;
prime = True;
for x in range(3, int(n**0.5 + 1), 2):
if n % x == 0:
prime = False;
break;
if prime:
return n
Correct logic, you are setting True when n % x ! = 0 for first time:
for x in range(3, int(n**0.5), 2):
if n % x ==0:
prime = False
else:
prime = True
should be:
prime = False
for x in range(3, int(n**0.5), 2):
if n % x ==0:
break
else:
prime = True
Read break and continue Statements, and else Clauses on Loops.
The shorter way of writing equivalent code will be (from #Steve Jesso):
prime = all(n % x != 0 for x in range(3, int(n**0.5), 2)
Generating big primes over and over can cost a lot of time. For this reason I used increments.
import random
def generate_big_prime(size):
p = random.randrange(2 ** (size - 1), 2 ** size - 1)
if p % 2 == 0:
p += 1
while not is_prime(p):
p += 2
return p
Where is_prime() is a primality test. I would recommend the Miller-Rabin primality test for its efficiency.

Categories