Generating large prime numbers in python - 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.

Related

How do I find the largest prime factor in an array?

I am solving problem 3 in euler project to find the largest prime factor of a certain number.
def findFactors(num: int)->list:
factors = []
for i in range(1, num+1):
if num%i == 0:
factors.append(i)
return factors
prime_factors = (findFactors(600851475143))
max= prime_factors[0]
num = 600851475143
for i in range(0, len(prime_factors)):
if (prime_factors[i] > max):
max = prime_factors[i]
print(f"The largest prime factor of the {num} is {max}")
When I run the code for "13195", the code runs correctly but when I run the code for the actual number i.e 600851475143, the code is not giving any output, neither any errors
I think while loop will perform better:
n = 600851475143
x = 2
while x * x < n:
while n % x == 0:
n = n // x
x = x + 1
print(n)
#6857
You need two functions. One to determine the factors of a positive integer and another to determine if a number is prime.
from functools import cache
from math import sqrt, floor
from functools import reduce
from time import perf_counter
#cache
def isprime(n):
if n < 2:
return False
if n == 2 or n == 3:
return True
if n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, floor(sqrt(n))+1, 6):
if n % i == 0 or n % (i + 2) == 0:
return False
return True
def factors(n):
if n > 0:
for f in sorted(set(reduce(list.__add__, ([i, n//i] for i in range(1, floor(sqrt(n)) + 1) if n % i == 0)))):
yield f
N = 600851475143
start_time = perf_counter()
f = [_f for _f in factors(N) if isprime(_f)]
end_time = perf_counter()
print(f[-1] if f else None, f'{end_time-start_time:.4f}s')
Output:
6857 0.0452s
Your code does work, but just takes too long. As someone pointed out, the number evaluated is indeed very big... Here it is required that you compute at least 10^12 division before it finishes.
Of course there are better ways to answer this problem. For instance, you need to look for factors only up to sqrt(n); or you could try to think about the sieve of eratosthenes.
You could use a recursive function:
from math import sqrt, floor
import time
def findFactors(n):
if n%2==0:
findFactors(int(n/i))
return
for i in range (3, floor(sqrt(n))+2, 2):
if n%i==0:
print (i)
findFactors(int(n/i))
return
print (n)
return
start=time.time()
findFactors(600851475143)
print (time.time()-start)
Output:
71
839
1471
6857
0.00026988983154296875

Print out a list of prime numbers in python

The question is: print out all numbers from 1 to 1000 that satisfy the two conditions:
Those are prime numbers
The numbers after being reversed are also prime numbers.
e.g., 13 satisfies (as 13 and 31 are prime numbers), but 19 does not satisfy (19 is a prime number, while 91 is not).
My codes:
def prime(n):
if n<2:
return False
for i in range(1, n):
if n%i == 0:
return False
else:
return True
def reverse(n):
List = []
while n>0:
List.append(n%10)
n = n//10
string = [str(integer) for integer in List]
a_string = "".join(string)
result = int(a_string)
print(result)
L = []
for i in range (1, 1000):
if prime(i) == prime(reverse(i)) == True:
L.append(i)
print(L)
Mine seems to contain some errors as the outcome is not as expected, either it shows none or still shows 19 in the list.
Thank you in advance!
First your prime method is wrong, because the loops starts at 1, and every numbre satisfies n%1 == 0 , it needs to starts at 2
def prime(n):
if n < 2:
return False
for i in range(2, n):
if n % i == 0:
return False
return True
Then your reverse method returns nothing so reverse(5) gives None, you have tried it manually.
def reverse(n):
values = []
while n > 0:
values.append(n % 10)
n = n // 10
return int("".join(map(str, values)))
Then simplify the condition to be
for i in range(1, 20):
if prime(i) and prime(reverse(i)):
L.append(i)
The reverse process can be done with string also, and so short that it can be inlined
L = []
for i in range(1, 20):
if prime(i) and prime(int(str(i)[::-1])):
L.append(i)
It would seem running prime twice is very inefficient. I would recommend the following:
def prime(n):
if n<2:
return False
for i in range(2, n):
if n%i == 0:
return False
return True
l = [i for i in range(1, 1001) if prime(i)]
print(*(x for x in l if int(str(x)[::-1]) in l))

Printing the sum of prime divisors of each number in a given range in python

Here's my code for printing the sum of prime divisors of each number between 18 to 25. But it is only printing 5.
For example:
18 has prime factors 2, 3 hence sum = 5,
19 is prime, hence sum of factors = 0,
20 has prime factors 2 and 5, hence sum = 7,
21 has prime factors 3 and 7, hence sum = 10,
22 has prime factors 2 and 11, hence sum = 13,
23 is prime. hence sum = 0,
24 has prime factors 2 and 3, hence sum = 5,
25 has prime factor 5, hence sum = 5
Therefore, it should print [5,0,7,10,13,0,5,5]
I believe I should use break statement but i tried it didn't work. As I am beginner in python, any kind of help much appreciated.
def isPrime(n):
i = 2
while i * i <= n:
# n has a factor, hence not a prime
if (n % i == 0):
return False
i += 1
# we reach here if n has no factors
# and hence n is a prime number
return True
def summ(l, r):
summ = 0
arrayofdivisors = []
arrayofsum = []
# iterate from lower to upper
for i in range(l, r + 1) :
# if i is prime, it has no factors
if (isPrime(i)) :
continue
for j in range(2, i):
# check if j is a prime factor of i
if (i % j == 0 and isPrime(j)) :
arrayofdivisors.append(j)
if(len(arrayofdivisors)>1):
ans = sum(arrayofdivisors)
arrayofsum.append(ans)
return arrayofsum
# Driver code
if __name__ == "__main__":
l = 18
r = 25
print(summ(l, r))
Try this
def isPrime(n) :
if (n <= 1) :
return False
if (n <= 3) :
return True
if (n % 2 == 0 or n % 3 == 0) :
return False
i = 5
while(i * i <= n) :
if (n % i == 0 or n % (i + 2) == 0) :
return False
i = i + 6
return True
def Sum(N):
SumOfPrimeDivisors = [0] * (N + 1)
for i in range(2, N + 1) :
if (SumOfPrimeDivisors[i] == 0) :
for j in range(i, N + 1, i) :
SumOfPrimeDivisors[j] += i
return SumOfPrimeDivisors[N]
arr=[]
for i in range(18,26):
if isPrime(i):
arr.append(0)
else:
arr.append(Sum(i))
print(arr)
It's almost impossible to tell because of the way you've formatted things, but the problem here is that your "return" statement is indented one position too far. Thus, you return at the end of the first loop, before it has a chance to check anything else. Un-indent the return arrayofsum and it should work.
Then, you are initializing arrayofdivisors outside the main loop, so it just kept getting larger and larger. Then, you weren't adding 0 to the list for prime numbers, as your spec required.
Note that if statements in Python do not need parentheses, like they do in C.
def isPrime(n):
i = 2
while i * i <= n:
# n has a factor, hence not a prime
if n % i == 0:
print(n,'not prime')
return False
i += 1
# we reach here if n has no factors
# and hence n is a prime number
print(n,"prime")
return True
def summ(l, r):
# iterate from lower to upper
arrayofsum = []
for i in range(l, r + 1) :
arrayofdivisors = []
# if i is prime, it has no factors
if isPrime(i):
arrayofsum.append(0)
continue
for j in range(2, i):
# check if j is a prime factor of i
if i % j == 0 and isPrime(j):
arrayofdivisors.append(j)
arrayofsum.append( sum(arrayofdivisors) )
return arrayofsum
# Driver code
if __name__ == "__main__":
l = 18
r = 25
print(summ(l, r))

Fast Prime Generator besides Sieve

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'
?

Python Prime Factors

Again im stuck on a problem..
I wanted to create a function that puts out all prim factors of a given number.
It was pretty much finished but it wouldnt put out correct factors for numbers which have the same prim factor more than once, for example: 20 - 5, 2, 2
So i added a while loop which checked if the product of all factors equals the number i put in.
Thanks for any help :)
prime_numbers = []
def prime_gen(upper_limit):
for i in range(2, upper_limit):
for j in range(2, i):
if i % j == 0:
break
else:
prime_numbers.append(i)
return prime_numbers
def list_product(list):
sum = 1
for i in list:
sum *= i
return sum
prime_factors = []
def prime_factor(number):
while list_product(prime_factors) != number: #without the while it checked every factor only once
for i in reversed(prime_gen(number)):
while number % i != 0:
break
else:
if i != 1:
number /= i
prime_factors.append(i)
continue
else:
break
prime_factor(20)
print (prime_factors)
Just use a for loop, getting you list of primes from prime_gen:
def prime_gen(upper_limit):
prime_numbers = [2]
for i in range(3, upper_limit,2):
for j in range(2, i):
if i % j == 0:
break
else:
prime_numbers.append(i)
return prime_numbers
def prime_factors(n):
p_f = []
for prime in prime_gen(n):
# while n is divisible keep adding the prime
while n % prime == 0:
p_f.append(prime)
# update n by dividing by the prime
n //= prime
if n > 1:
p_f.append(n)
return p_f
print(prime_factors(40))
[2, 2, 2, 5] # -> 2*2*2*5
If you take 40 as an example:
(40, 2) # first prime 2, 40 is divisible by 2
(20, 2) # 40 //= 2 == 20, 20 is divisible by 2
(10, 2) # 20 //= 2 == 10, 10 is divisible by 2
(5, 5) # 10 //=2 == 5, 5 is not evenly divisible by 2 or 3 so we get 5
If you want a fast way to generate the primes, you can use a sieve:
from math import sqrt
def sieve_of_eratosthenes(n):
primes = range(3, n + 1, 2) # primes above 2 must be odd so start at three and increase by 2
for base in xrange(len(primes)):
if primes[base] is None:
continue
if primes[base] >= sqrt(n): # stop at sqrt of n
break
for i in xrange(base + (base + 1) * primes[base], len(primes), primes[base]):
primes[i] = None
primes.insert(0,2)
sieve=filter(None, primes)
return sieve
The error you are getting (TypeError: 'float' object cannot be interpreted as an integer) is ultimately caused by this statement:
number /= i
In Python 3, the result of /= is always a float. To perform integer division (so that number remains an integer), use:
number //= i
After fixing this, you'll find that you have a logic error that causes an infinite loop.

Categories