Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I used some code taken from Rosetta Code. I renamed a few things but I didn't really change anything.
import random
def is_probable_prime(n, num_trials = 5):
assert n >= 2
if n == 2:
return True
if n % 2 == 0:
return False
s = 0
d = n-1
while True:
quotient, remainder = divmod(d, 2)
if remainder == 1:
break
s += 1
d = quotient
assert(2**s * d == n-1)
def try_composite(a):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2**i * d, n) == n-1:
return False
return True
for i in range(num_trials):
a = random.randrange(2, n)
if try_composite(a):
return False
return True
It pretty closely matches some psuedocode. However, when I test the number
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901
it returns False. Other (python and java) implementations of Miller-Rabin return True for probable prime. After some testing, try_composite returns True after only 2 rounds! I would really like to know any error, I'm guessing a mis-indent or some feature I don't know about.
In your try_composite function, the for loop should be for i in range(1,s). Do not test the case where i is zero.
EDIT: Also, you are missing a test in your try_composite function. Here is my version of the pseudocode:
def isPrime(n, k=5):
def isComposite(s, d):
x = pow(randrange(2,n-1), d, n)
if x == 1 or x == n-1: return False
for r in range(1, s):
x = pow(x, 2, n)
if x == 1: return True
if x == n-1: return False
return True
if n < 2: return False
for p in [2, 3, 5, 7, 11, 13, 17]:
if n % p == 0: return n == p
s, d = 0, n-1
while d % 2 == 0: s, d = s+1, d/2
for i in range(k):
if isComposite(s, d): return False
return True
It's too bad that Python doesn't allow labels on break or continue statements. Here's pseudocode for a much prettier version of the function:
function isPrime(n, k=5)
if n < 2 then return False
for p in [2,3,5,7,11,13,17,19,23,29]
if n % p == 0 then return n == p
s, d = 0, n-1
while d % 2 == 0
s, d = s+1, d/2
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
if x == n-1 then next i
return False
return True
Notice the two places where the control flow goes to next i. There is no good way to write that in Python. One choice uses an extra boolean variable that can be set and tested to determine when to bypass the rest of the code. The other choice, which I took above, is to write a local function to perform the task. This "loop-and-a-half" idiom is convenient and useful; it was proposed in PEP 3136 and rejected by Guido.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I've started learning Python 2 days ago and my friends said Project Euler is good to learn. I solved the first 9 Problems and although it was very hard it somehow worked every time. But now im stuck and I dont know why. My answer is just about 100000 off (doesnt seem that much when working with those huge numbers). So if one of you has the time to help me find my fault it would be highly appreciated.
x = 2
z = 0
def is_prime(x):
if x == 2:
return True
for n in range(2, 1415):
if x % n == 0:
return False
return True
while x < 2000000:
if is_prime(x) == True:
z = z + x
x = x + 1
elif x >= 2000000:
break
else:
x = x + 1
print(z)
The problem is the function that verifies that the number is prime.
Here's a working function:
def is_prime(x):
if (x<2):
return False
div = 2
while (div < x):
if (x%div == 0):
return False
div += 1
return True
Edit:
Here's a way faster solution:
x = 2
z = 0
def is_prime2(n):
if n == 2:
return True
if n & 1 == 0:
return False
d= 3
while d * d <= n:
if n % d == 0:
return False
d= d + 2
return True
while x <= 2000000:
if is_prime2(x) == True:
z = z + x
x = x + 1
else:
x = x + 1
print(z)
Your is_prime function is the source of your error, specifically,
for n in range(2, 1415)
This will say that no number below 1415 is prime because, for example, 7 is a prime number but is in the range 2-1414, so 7%7 is 0.
Keeping the same basic formatting, we can rewrite it as such, using math to calculate the square root for each number (which is where the 1415 came from). If you don't want to import math, you can make it range(2,x), but that will have a very long computation time.
def is_prime(x):
if x == 2:
return True
for n in range(2, math.ceil(math.sqrt(x))+1): # +1 is for how python handles ranges
if (x % n) == 0:
return False
return True
You can also clean up your code a little bit like this (keeping the same general format):
for x in range(2, 2000000+1): # again, +1 for how python handles ranges
if is_prime(x): # you don't need == True, the True return makes the if statement True
z += x
print(z)
I can't comment so i have a question... you run the code and what is happening? I copy-paste your code and i couldn't run it. So i have this solution for you if is not running
x = 2
z = 0
def is_prime(x):
if x == 2:
return True
for n in range(2, 1415):
if x % n == 0:
return False
return True
is_prime = is_prime(x)
while x < 2000000:
if is_prime == True:
z = z + x
x = x + 1
elif x >= 2000000:
break
else:
x = x + 1
print(z)
This is only if is not running. As the guys said on your comments be more specific about your problem.
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))
I tried to solve Project Euler #37:
The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.
Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
I wrote my code in Python but I am facing weird issues.
Here's my code:
def isPrime(n):
if n == 2 or n == 3 or n == 5: return True
if n < 2 or n%2 == 0: return False
if n < 9: return True
if n%3 == 0: return False
if n%5 == 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 gen(nb):
results = []
nb_str = str(nb)
for k in range(0, len(nb_str) - 1):
results.append(nb_str[k:])
results.append(nb_str[-k:])
return results
def check(nb):
for t in gen(nb):
if not isPrime(int(t)):
return False
return True
c = 0
s = 0
i = 2
while c != 11:
if check(i):
c += 1
s += i
i += 1
print(s)
Where does the error come from? (The expected result is 748317)
I suspect the errors coming from the results list
Yes, the gen() function is not working correctly as your slicing is off, also, you count 2, 3, 5 and 7 as truncatable primes which the question denies.
The second slice should be the other way around:
>>> s = 'abcd'
>>> for i in range(1,len(s)-1):
... print(s[i:])
... print(s[:-i])
...
bcd
abc
cd
ab
which we can see produces the right strings.
Altogether then, the function should be:
def gen(nb):
results = [nb]
nb_str = str(nb)
for k in range(1, len(nb_str)):
results.append(int(nb_str[k:]))
results.append(int(nb_str[:-k]))
return results
note I also added a string to int conversion - not sure how Python didn't make that obvious for you :/
And before get the full solution, Project Euler nearly always gives you an example which you can use to check your code:
>>> check(3797)
True
You must also add a condition in the check function to return False if the number is 2, 3, 5 or 7 as this is stated clearly in the question.
And the result is the expected: 748317.
Joe Iddon has explained the error in your code, but you can speed it up a little by turning gen into an actual generator. That way, you can stop checking the results for a given nb as soon as you detect a composite number (and gen will stop generating them). I've also made a few minor tweaks to your primality tester. Remember, the or operator short-circuits, so if a is True-ish in a or b then it doesn't bother evaluating b.
def isPrime(n):
if n in {2, 3, 5, 7}:
return True
if n < 2 or n%2 == 0:
return False
if n%3 == 0 or n%5 == 0:
return False
r = int(n**0.5)
f = 5
while f <= r:
if n%f == 0 or n%(f+2) == 0:
return False
f += 6
return True
def gen(nb):
yield nb
nb_str = str(nb)
for k in range(1, len(nb_str)):
yield int(nb_str[k:])
yield int(nb_str[:-k])
def check(nb):
for t in gen(nb):
if not isPrime(t):
return False
return True
c = s = 0
# Don't check single digit primes
i = 11
while c < 11:
if check(i):
c += 1
s += i
print(i)
i += 2
print('sum', s)
output
23
37
53
73
313
317
373
797
3137
3797
739397
sum 748317
In fact, you can get rid of the check function, and replace it with all, which also short-circuits, like or does. So you can replace the
if check(i):
with
if all(map(isPrime, gen(i))):
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'
?
I have this pseudocode for a Miller-Rabin primality tester:
function isPrime(n, k=5)
if n < 2 then return False
for p in [2,3,5,7,11,13,17,19,23,29]
if n % p == 0 then return n == p
s, d = 0, n-1
while d % 2 == 0
s, d = s+1, d/2
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
if x == n-1 then next i
return False
return True
But translating that to Python is hard because of the next i statement in the inner for loop, which must break two loops. There is no goto in Python. Other questioners who have asked this question on Stack Overflow have been told to use a local function with a return, or a try/except condition, or an additional boolean flag, but those solutions either don't apply here or would greatly uglify this lovely pseudocode.
What is the Pythonic approach to this problem?
I think the pythonic approach would be try/except, readability would prefer a method or a boolean, but I think that this is solvable by adding a single line:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break #*
if x != n-1: #added line
return False
return True
breaking on the line marked with #* is problematic because it returns false, but if we fix that it's just like "next i".
Another solution, suggested by tobias_k, is to use for/else:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break
else: #added line
return False
return True
return False statement would not be called if the loop was break-ed - only if it was exhausted.
You can use break and continue witn a for: else.
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
# Use 'continue' to go to next i (skip inner loop).
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
# Use 'break' to exit this loop and go to next i
# since this loop is at the end of the i loop.
if x == n-1 then next i
else:
# This is only reached if no `break` occurred
return False
return True