Fastest way to find prime in intervals - python

I tried searching StackOverflow and some other sources to find the fastest way to get a prime number within some interval but I didn't find any efficient way, so here is my code:
def prime(lower,upper):
prime_num = []
for num in range(lower, upper + 1):
# all prime numbers are greater than 1
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
prime_num.append(num)
return prime_num
Can I make this more efficient?
I tried finding my answer in Fastest way to find prime number but I didn't find prime numbers in intervals.

I wrote an equation based prime finder using MillerRabin, it's not as fast as a next_prime finder that sieves, but it can create large primes and you get the equation it used to do it. Here is an example. Following that is the code:
In [5]: random_powers_of_2_prime_finder(1700)
Out[5]: 'pow_mod_p2(27667926810353357467837030512965232809390030031226210665153053230366733641224969190749433786036367429621811172950201894317760707656743515868441833458231399831181835090133016121983538940390210139495308488162621251038899539040754356082290519897317296011451440743372490592978807226034368488897495284627000283052473128881567140583900869955672587100845212926471955871127908735971483320243645947895142869961737653915035227117609878654364103786076604155505752302208115738401922695154233285466309546195881192879100630465, 2**1700-1, 2**1700) = 39813813626508820802866840332930483915032503127272745949035409006826553224524022617054655998698265075307606470641844262425466307284799062400415723706121978318083341480570093257346685775812379517688088750320304825524129104843315625728552273405257012724890746036676690819264523213918417013254746343166475026521678315406258681897811019418959153156539529686266438553210337341886173951710073382062000738529177807356144889399957163774682298839265163964939160419147731528735814055956971057054406988006642001090729179713'
or use to get the answer directly:
In [6]: random_powers_of_2_prime_finder(1700, withstats=False)
Out[6]: 4294700745548823167814331026002277003506280507463037204789057278997393231742311262730598677178338843033513290622514923311878829768955491790776416394211091580729947152858233850115018443160652214481910152534141980349815095067950295723412327595876094583434338271661005996561619688026571936782640346943257209115949079332605276629723961466102207851395372367417030036395877110498443231648303290010952093560918409759519145163112934517372716658602133001390012193450373443470282242835941058763834226551786349290424923951
The code:
import random
import math
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 ltrailing(N):
return len(str(bin(N))) - len(str(bin(N)).rstrip('0'))
def pow_mod_p2(x, y, z):
"4-5 times faster than pow for powers of 2"
number = 1
while y:
if y & 1:
number = modular_powerxz(number * x, z)
y >>= 1
x = modular_powerxz(x * x, z)
return number
def modular_powerxz(num, z, bitlength=1, offset=0):
xpowers = 1<<(z.bit_length()-bitlength)
if ((num+1) & (xpowers-1)) == 0:
return ( num & ( xpowers -bitlength)) + 2
elif offset == -1:
return ( num & ( xpowers -bitlength)) + 1
elif offset == 0:
return ( num & ( xpowers -bitlength))
elif offset == 1:
return ( num & ( xpowers -bitlength)) - 1
elif offset == 2:
return ( num & ( xpowers -bitlength)) - 2
def MillerRabin(N, primetest, iterx, powx, withstats=False):
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
PRIMES=list(primes_sieve2(1000000))
def mr_isprime(N, withstats=False):
if N == 2:
return True
if N % 2 == 0:
return False
if N < 2:
return False
if N in PRIMES:
return True
for xx in PRIMES:
if N % xx == 0:
return False
iterx = ltrailing(N - 1)
k = pow_mod_p2(N, (1<<N.bit_length())-1, 1<<N.bit_length()) - 1
t = N >> iterx
tests = [k+1, k+2, k, k-2, k-1]
for primetest in tests:
if primetest >= N:
primetest %= N
if primetest >= 2:
if MillerRabin(N, primetest, iterx, t, withstats) == False:
return False
return True
def lars_last_modulus_powers_of_two(hm):
return math.gcd(hm, 1<<hm.bit_length())
def random_powers_of_2_prime_finder(powersnumber, primeanswer=False, withstats=True):
while True:
randnum = random.randrange((1<<(powersnumber-1))-1, (1<<powersnumber)-1,2)
while lars_last_modulus_powers_of_two(randnum) == 2 and mr_isprime(randnum//2) == False:
randnum = random.randrange((1<<(powersnumber-1))-1, (1<<powersnumber)-1,2)
answer = randnum//2
# This option makes the finding of a prime much longer, i would suggest not using it as
# the whole point is a prime answer.
if primeanswer == True:
if mr_isprime(answer) == False:
continue
powers2find = pow_mod_p2(answer, (1<<powersnumber)-1, 1<<powersnumber)
if mr_isprime(powers2find) == True:
break
else:
continue
if withstats == False:
return powers2find
elif withstats == True:
return f"pow_mod_p2({answer}, 2**{powersnumber}-1, 2**{powersnumber}) = {powers2find}"
return powers2find
def nextprime(N):
N+=2
while not mr_isprime(N):
N+=2
return N
def get_primes(lower, upper):
lower = lower|1
upper = upper|1
vv = []
if mr_isprime(lower):
vv.append(lower)
else:
vv=[nextprime(lower)]
while vv[-1] < upper:
vv.append(nextprime(vv[-1]))
return vv
Here is an example like yours:
In [1538]: cc = get_primes(1009732533765201, 1009732533767201)
In [1539]: print(cc)
[1009732533765251, 1009732533765281, 1009732533765289, 1009732533765301, 1009732533765341, 1009732533765379, 1009732533765481, 1009732533765493, 1009732533765509, 1009732533765521, 1009732533765539, 1009732533765547, 1009732533765559, 1009732533765589, 1009732533765623, 1009732533765749, 1009732533765751, 1009732533765757, 1009732533765773, 1009732533765821, 1009732533765859, 1009732533765889, 1009732533765899, 1009732533765929, 1009732533765947, 1009732533766063, 1009732533766069, 1009732533766079, 1009732533766093, 1009732533766109, 1009732533766189, 1009732533766211, 1009732533766249, 1009732533766283, 1009732533766337, 1009732533766343, 1009732533766421, 1009732533766427, 1009732533766457, 1009732533766531, 1009732533766631, 1009732533766643, 1009732533766667, 1009732533766703, 1009732533766727, 1009732533766751, 1009732533766763, 1009732533766807, 1009732533766811, 1009732533766829, 1009732533766843, 1009732533766877, 1009732533766909, 1009732533766933, 1009732533766937, 1009732533766973, 1009732533767029, 1009732533767039, 1009732533767093, 1009732533767101, 1009732533767147, 1009732533767159, 1009732533767161, 1009732533767183, 1009732533767197, 1009732533767233]

Yes. In general, use:
Sieve of Eratosthenes
Miller-Rabin Primality Test
Other options include trying a compiled language, like C++, but I think that isn't what you're looking for, since you've asked about Python.

Yes, you can make it more efficient. As has been mentioned, for very large numbers use Miller-Rabin. For smaller ranges use the Sieve of Eratosthenes. However, apart from that, your prime checker code is very inefficient.
2 is the only even prime number, which can save you doing half the work you do.
You only need to check up to the square root of the number you are testing. In any pair of factors: f and n/f, one is guaranteed to be less then or equal to the square root of the number being tested. Once you find a factor then the number is composite.
My Python is not good, so this is in pseudocode:
isPrime(num)
// Negatives, 0, 1 are not prime.
if (num < 2) return false
// Even numbers: 2 is the only even prime.
if (num % 2 == 0) return (num == 2)
// Odd numbers have only odd factors.
limit <- 1 + sqrt(num)
for (i <- 3 to limit step 2)
if (num % i == 0) return false
// No factors found so num is prime
return true
end isPrime

Related

Having trouble getting Miller-Rabin primality test in Python

I have been trying to implement Miller-Rabin primality test in Python. Unfortunately there seems to be a problem on some prime numbers. Any help is appreciated.
Code:
def _isPrime(n):
if n % 2 == 0:
return False
a = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
s, d = _Apart(n) # turns it into 2^s x d
print(s, d)
basePrime = False
isPrime = True
for base in a:
if base >= n-2:
break
if isPrime == False and basePrime == False:
return False
witness = pow(base, d)
if (witness % n) == 1 or (witness % n) == (n-1):
basePrime = True
continue
else:
basePrime = False
for r in range(1, s):
witness = pow(base, pow(2, r) * d)
if (witness % n) != ( n - 1 ):
isPrime = False
return True
Test:
isPrime(17)
Expected:
True
Result:
False
I wrote a Miller Rabin test that is deterministic, no need for random numbers. This implementation is for python 3.7. In python 3.8, llinear_diophantinex can be replaced with pow(x, -1, y). Also i used gmpy2 as it's very fast, but you can just replace the gmpy2 statements with normal pow if you can't use that, and just remove the gmpy2.mpz() wrappers since those are just used to overload operators.
import gmpy2
sinn = 2110229697309202254897383305762150945330987087513434511395506048950594976569434432057019507105035289374307720719984431280856161609820548842778454256113246763860786119268583367543952735347969627478873317341364209555365064365565504232770227619462128918701942169785585423104678142850200975026619010035331023744330713985615650556129731348659986462960062760308034462660525448390420668021248422741300646552941285862310410598374242189448623917196191138254637812716211329113836605859918549332304189053950819346551095911511755911832183789503704294770046935064469435830299623205136625543859303686699678929069468518950480476841246805908501510754550017255944080874819287974625925494008373883250410775902993163965873632474224574883242826458163446781002284368017611606202344050570737818087202137703099075773680753707346415849787963446390136517016131227807076254668461445862154978026041507116570585784569893773262639243954090283224759975513502582494002154146757110676408972377044584495342170277522887809749465855954126593100747444378301829661568735873345178089061677917127496915956539418931430313218084338374827152407795095072639044306222222695685778907958272820576498682506540189586657786292950574081739269257159839589987847266550007783514316481286222515710538845836151864127815058116482680058626451349913138908040817800742009650450811565324184631847563730941344941348929727603343965091116543702880556850922077216848669966268219928808236163268726995495688157209747596437162960244538054993785127947211290438554095851924381172697827312534174244295581184309147813790451951453564726742200569263225639113681905176376701339808868274637448606821696026703034737428319530072483125495383057919894902076566679023694181381398377144302767983385253577700652358431959604517728821603076762965129019244904679015099154368058005173028200266632883632953133017055122970338782493475762548347258351148037427739052271661340801912188203749647918379812483260399614599813650518046331670764766419886619324840045611486524123102046413946014624119568013100078163986683199814025915420877588778260860713148420321896163326473203441644820182490479899368048072263481024886708136521847014624735722333931331098969321911443978386868675912141648200500219168920887757573018380579532261231821382787339600631297820996466930957801607217549420247654458172818940238337170577825003408756362106088558651381993611741503374243481167926898332728164900189941804942580426055589622673679047058619682175301326905577843405270203660160407401675700528981573327582844330828861745574031416926871562443652858767649050943181353635950301154441954046214987718582670685455252774874198771086552440702483933126644594300464549471422237478151976561680719370424626162642534252062987911763456822609569209140676822858933588602318066530038691463577379331113471591913447226829868760176810195567325921301390329055242213842898142597360121925124635965685365925901913816717677946911762631634793638450106377437599347740569467683272089859392249351406815344105961234868327316964137925419770514177021722214309784062017826024217906664090209434553785436385765927274067126192143337589109608949427467825999057058702263715338956534536892852849984934736685814891286495169007648767081688963426768409476169071460997622740467533572971356017575900999100928776382541052696124463195981888715845688808970103527288822088031150716134784735332326775370417950625124642515148342694377095213470544739900830244879573205335578256682901821773047071352497997708791157012233232529777513203024818391621220967964874173106990772425289900446640237659116713251437567138729645677868024033209183367071421651937808005637679844370347367922676824239404492688418047080583797577102267329067247758368597488680401670673861120323439239792549053895366970423259196919428554146265587250617656401028722578111927104663315250291888502226235291264834968061065817079511872899991276288365723969841290984981957389126603952133124328219936785870274843554107325931034103072894378438818494802517594594270034007832922248742746517915210656205746338575621725899098414488628833412591266637224507533934158213117522503993423240638893845121918647788013
def llinear_diophantinex(a, b, divmodx=1, x=1, y=0, offset=0, withstats=False, pow_mod_p2=False):
origa, origb = a, gmpy2.mpz(b)
r=a
q = a//b
prevq=1
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 = gmpy2.mpz(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 ffs(x):
"""Returns the index, counting from 0, of the
least significant set bit in `x`.
"""
return (x&-x).bit_length()-1
def MillerRabin(arglist):
N = arglist[0]
primetest = arglist[1]
iterx = arglist[2]
powx = arglist[3]
withstats = arglist[4]
primetest = gmpy2.powmod(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):
primetest = gmpy2.powmod(primetest, 2, N)
if withstats == True:
print("else: ", primetest)
if primetest == N - 1: return True
if primetest == 1: return False
return False
def sfactorint_isprime(N, withstats=False):
N = gmpy2.mpz(N)
from multiprocessing import Pool
if N <= 1: return False
if N == 2:
return True
if N % 2 == 0:
return False
if N < 2:
return False
# Add Trial Factoring here to speed up smaller factored number testing
iterx = ffs(N-1)
""" This k test is an 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.
"""
k = llinear_diophantinex(N, 1<<N.bit_length(), pow_mod_p2=True) - 1
t = N >> iterx
tests = [k-2, k-1, k, k+1, k+2]
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(5) as p:
s=p.map(MillerRabin, arglist)
if s.count(True) == len(arglist): return True
else: return False
return s
Recently I also tried to implement this algorithm in the deterministic form, as shown in Miller Test, and ran into the same problem. I couldn't figure out why it failed for some numbers so I decided to implement the 'complete' Miller-Rabin Test and it worked.
I should warn that it gets slow quickly as n increases. It's advised to use some numeric library like Numpy to optimize the calculations.
With some tweaks on your code it can be achieved:
import random
def _isPrime(n):
if n % 2 == 0:
return False
rounds = 40 # Determines the accuracy of the test
s, d = _Apart(n) # Turns it into 2^s x d + 1
for _ in range(rounds):
base = random.randrange(2, n-1) # Randomly selects a base
witness = pow(base, d)
if (witness % n) == 1 or (witness % n) == (n-1):
continue
for _ in range(1, s):
witness = pow(witness, 2) % n
if witness == (n-1):
break
else: # if the for-loop is not 'broken', n is not prime
return False
return True
def is_prime(n):
"""returns True if n is prime else False"""
if n < 5 or n & 1 == 0 or n % 3 == 0:
return 2 <= n <= 3
s = ((n - 1) & (1 - n)).bit_length() - 1
d = n >> s
for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
p = pow(a, d, n)
if p == 1 or p == n - 1 or a % n == 0:
continue
for _ in range(s):
p = (p * p) % n
if p == n - 1:
break
else:
return False
return True

Python - function returns true when a given number is a prime number or else false

Hi I'm a beginner and I'm stuck on this question that wants me to use only while loop to solve. The question wants me to write a function that returns True when the given number is a prime number and it returns False if the given number is not a prime number.
My code so far:
def is_prime(n):
i = 2
while i <= n//2:
if n%i != 0:
return True
else:
return False
i+=1
The problem I have is I think my code displays the correct output for numbers 4 and above and it returns 'None' for 1, 2, and 3. I've debugged it and I think the problem is the while loop condition. But I don't know how to fix it. I would appreciate it if any of you pros can help me out!
edit:
I changed the while condition but 1 still returns None.. and 2 returns False when it's supposed to return True
def is_prime(n):
i = 2
while i <= n:
if n%i != 0:
return True
else:
return False
i+=1
import math;
def is_prime(n):
i = 2
while i < max(math.sqrt(n),2):
if n%i != 0:
return True
else:
return False
if i == 2:
i+=1
else
i+=2
You could hard-code these 3 cases, in case you dont want to use sqrt:
def is_prime(n):
i = 2
if n in (1,3):
return True
elif n == 2:
return False
while i <= n//2:
if n%i != 0:
return True
else:
return False
i+=1
for x in range(1, 5):
print(x, '=', is_prime(x))
Output:
(1, '=', True)
(2, '=', False)
(3, '=', True)
(4, '=', False)
Want to get really fancy? Make a Sieve of Eratosthenes:
def is_prime(n):
a = list()
# Assume all are prime
a[0:n+1] = (n+1)*[1]
# Start with removing even numbers
i = 2
while i*i <= n:
print ("I: ", i)
# Set all divisible by i to 0
a[0:n+1:i] = len(a[0:n+1:i])*[0]
# If a[n] is zero, return False
if a[n] == 0:
return False
# Increment i until we have a prime number
while a[i] == 0:
i+=1
if a[n] == 0:
return False
else:
return True
If you want to impress your lesson teacher you can show him a fast probabilistic prime number isprime for numbers larger than 2**50. I haven't found any errors in it after weeks of cpu time stress testing it on a 6 core AMD:
import random
import math
def lars_last_modulus_powers_of_two(hm):
return math.gcd(hm, 1<<hm.bit_length())
def fast_probabilistic_isprime(hm):
if hm < 2**50:
return "This is to only be used on numbers greater than 2**50"
if lars_last_modulus_powers_of_two(hm+hm) != 2:
return False
if pow(2, hm-1, hm) == 1:
return True
else:
return False
def fast_probabilistic_next_prime(hm):
if hm < 2**50:
return "This is to only be used on numbers greater than 2**50"
if hm % 2 == 0:
hm = hm + 1
hm += 2
while fast_probabilistic_isprime(hm) == False:
hm += 2
return hm
""" hm here is bitlength, which must be larger than 50.
usage is create_probabilistic_prime(1000)
"""
def create_probabilistic_prime(hm):
if 2**hm < 2**50:
return "This is to only be used on numbers greater than 2**50"
num = random.randint(2**hm,2**(hm+1))
return fast_probabilistic_next_prime(num)

How do i check if the number is semi prime

def is_prime(num):
if num > 1:
for i in range(2,num):
return False if (num % i) == 0:
if (num % i) == 0:
return False
return True if prime
else:
return True
return False if not prime
else:
return False
def is_semiprime():
n = int(input("Enter a number to find out if its semiprime or not\n>>> "))
for d1 in range(2, int(n**.5)):
if n % d1 == 0:
d2 = int(n / d1)
is_prime(d1) and is_prime(d2) go through and don't tell me there true or false they just send blank lines.
return is_prime(d1) and is_prime(d2)
return False
is_semiprime()
when it Returns is_prime(d1) and is_prime(d2) if they are both True then return True
A semi-prime number is a number that's the product of two prime numbers. So the algorithm is simple:
Find one divisor of the number, call it d1.
Divide the number by d1 to get a second divisor, d2.
Test whether both d1 and d2 are prime. If they are, then the original number is semi-prime.
Code:
def is_semiprime(n):
for d1 in range(2, int(n**.5)+1):
if n % d1 == 0:
d2 = n / d1
return is_prime(d1) and is_prime(d2)
return False
def is_prime(n):
if n == 2 or n == 3: return True
if n < 2 or n%2 == 0: return False
if n < 9: return True
if n%3 == 0: return False
r = int(n**0.5)
f = 5
while f <= r:
if n%f == 0: return False
if n%(f+2) == 0: return False
f +=6
return True
def ask_semiprime():
num = int(input("What number would you like to check?"))
if is_semiprime(num):
print(num, " is semiprime")
else:
print(num, " is not semiprime")
ask_semiprime()
I copied the is_prime function from isPrime Function for Python Language
number=int(input())
s=number
x=[]
for i in range(2,number+1):
if s%i==0:
x.append(i)
s=s//I
if s==i or (i>s and s!=1):
x.append(s)
if len(x)==2:
print(f"{number} is a semiprime number because it is the product of Tow primes: ",end="")
else:
print(f"{number} is not a semiprime number because it is the product of {len(x)} primes: ",end="")
for i in x:
if i==x[-1]:
print(i)
else:
print(str(i)+"*",end="")
def check_prime(n): #for checking wheather prime or not
if n > 1:
if n == 2: return True
for i in range(2,n):
if n % i == 0:
return False
break
return True
return False
def primeproduct(m): #for checking wheather prime product or not
if m >= 0:
for i in range(1,m):
if m%i == 0 and check_prime(i) and check_prime(m//i):
return True
break
return False
this may help

Function testing for primes not working as needed

It's supposed to find out if the given input is a prime number or not.
def is_prime(x):
if x <= 1:
return False
elif x == 2 or x == 3:
return True
else:
for n in range(2, x-1):
if x % n == 0:
return False
else:
return True
But
is_prime(9)
gives True where it should return False.
I can't find the bug, need help.
You return True the moment you find a factor that doesn't divide x evenly. 2 doesn't divide 9 so you return True then:
>>> x = 9
>>> n = 2
>>> if x % n == 0:
... print False
... else:
... print True
...
True
You need only return True when you determined that no factors exist, so outside your loop:
for n in range(2, x-1):
if x % n == 0:
return False
return True
You don't need to test up to x - 1, testing up to int(x ** 0.5) + 1 is enough (so up to the square root):
def is_prime(x):
if x <= 1:
return False
if x in (2, 3):
return True
for n in range(2, int(x ** 0.5) + 1):
if x % n == 0:
return False
return True

SPOJ Prime Generator

I guess this isn't the best question in the world, but I can't seem to figure why on earth this code:
def isprime(num):
if num < 2:
return False
if num == 2:
return True
if num % 2 == 0:
return False
for divisor in range(3, int(num ** 0.5) + 1, 2):
if num % divisor == 0:
return False
return True
def case(mini, maxi):
for i in range(mini, maxi + 1):
if isprime(i):
print(i)
test = [line.split() for line in input().split("\n")[1:]]
for line in test:
mini, maxi = [int(num) for num in line]
case(mini, maxi)
print()
does not satisfy SPOJ Question 2?? The prime tester has worked well for me before, and the code works on the example inputs.

Categories

Resources