mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
102 lines
2.2 KiB
Python
102 lines
2.2 KiB
Python
''' mbinary
|
|
#########################################################################
|
|
# File : isPrime.py
|
|
# Author: mbinary
|
|
# Mail: zhuheqin1@gmail.com
|
|
# Blog: https://mbinary.xyz
|
|
# Github: https://github.com/mbinary
|
|
# Created Time: 2018-03-04 21:34
|
|
# Description:
|
|
#########################################################################
|
|
'''
|
|
from random import randint
|
|
|
|
|
|
def quickMulMod(a, b, m):
|
|
'''a*b%m, quick'''
|
|
ret = 0
|
|
while b:
|
|
if b & 1:
|
|
ret = (a+ret) % m
|
|
b //= 2
|
|
a = (a+a) % m
|
|
return ret
|
|
|
|
|
|
def quickPowMod(a, b, m):
|
|
'''a^b %m, quick, O(logn)'''
|
|
ret = 1
|
|
while b:
|
|
if b & 1:
|
|
ret = quickMulMod(ret, a, m)
|
|
b //= 2
|
|
a = quickMulMod(a, a, m)
|
|
return ret
|
|
|
|
|
|
def isPrime(n, t=5):
|
|
'''miller rabin primality test, a probability result
|
|
t is the number of iteration(witness)
|
|
'''
|
|
t = min(n-3, t)
|
|
if n < 2:
|
|
print('[Error]: {} can\'t be classed with prime or composite'.format(n))
|
|
return
|
|
if n == 2:
|
|
return True
|
|
d = n-1
|
|
r = 0
|
|
while d % 2 == 0:
|
|
r += 1
|
|
d //= 2
|
|
tested = set()
|
|
for i in range(t):
|
|
a = randint(2, n-2)
|
|
while a in tested:
|
|
a = randint(2, n-2)
|
|
tested.add(a)
|
|
x = quickPowMod(a, d, n)
|
|
if x == 1 or x == n-1:
|
|
continue # success,
|
|
for j in range(r-1):
|
|
x = quickMulMod(x, x, n)
|
|
if x == n-1:
|
|
break
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
|
|
'''
|
|
we shouldn't use Fermat's little theory
|
|
Namyly:
|
|
For a prime p, and any number a where (a,n)=1
|
|
a ^(p-1) \equiv 1 (mod p)
|
|
|
|
The inverse theorem of it is not True.
|
|
|
|
a counter-example: 2^340 \equiv 1 (mod 341), but 341 is a composite
|
|
'''
|
|
|
|
|
|
def twoDivideFind(x, li):
|
|
a, b = 0, len(li)
|
|
while a <= b:
|
|
mid = (a+b)//2
|
|
if li[mid] < x:
|
|
a = mid+1
|
|
elif li[mid] > x:
|
|
b = mid-1
|
|
else:
|
|
return mid
|
|
return -1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
n = 100
|
|
print('prime numbers below', n)
|
|
print([i for i in range(n) if isPrime(i)])
|
|
while 1:
|
|
n = int(input('n: '))
|
|
print(isPrime(n))
|