-
寻找素数因子
寻找一个数的素因子的最显而易见的办法是:尝试将这个数用比其小大于等于2的整数试除,将能整除的数(因子)保存起来,问题转化为求 这个数 / (除) 保存的因子 的素数因子。
Python实现如下:
def splitPrime(number) -> list:
# 素数因子
factor = []
i = 3
# 最大可能因子
# 提取出偶数
while number > 1 and number % 2 == 0:
factor.append(2)
number //= 2
# 寻找奇因子
max_factor = int(sqrt(number))
while i <= max_factor:
while number % i == 0:
factor.append(i)
number //= i
max_factor = int(sqrt(number))
i += 2
factor.append(number)
return factor
pass
if __name__ == "__main__":
ret = splitPrime(999979799744544)
print(ret)
print("去重:")
print(set(ret))
ac = 1
for i in range(0, len(ret)):
ac *= ret[i]
print(ac)
测试结果:
2.寻找素数
埃拉托色尼筛法
给定整数n,寻找2~n的最大素数
1.去除2的倍数
2.去除3的倍数(有些也是2的倍数,已被去除,比如6,12)
.
.
.
3.去除sqrt(n)的倍数
时间复杂度为:O(N*log(logN)),算法适用于小数据
Python实现如下:
def findPrime(number) -> list:
# 合数为true
is_composite = [True]*(number+1)
for i in range(2, number + 1):
is_composite[i] = False
# 去除2的倍数
for i in range(4, number + 1, 2):
is_composite[i] = True
# 去除大于2的素数的倍数
stop_at = int(sqrt(number))
next_prime = 3
while next_prime <= stop_at:
# 去除next_prime的倍数
for k in range(next_prime * 2, number+1, next_prime):
is_composite[k] = True
next_prime += 2
while next_prime <= number and is_composite[next_prime]:
next_prime += 2
prime_list = []
for i in range(2, number+1):
if not is_composite[i]:
prime_list.append(i)
print(prime_list)
return prime_list
if __name__ == "__main__":
findPrime(9999)
测试结果:
3.素性测试(小费马定理)
判断数p是否是素数:
小费马定理表明:
如果p是素数,则1<=n<p,且pow(n,p-1) % p ==1
注意:
1.即使p不是素数,也有可能成立 1<=n<=p,且pow(n,p-1) % p ==1,此时称n为“费马骗子”,相反不成立成为“费马证人”
2.可以证明对于自然数p,1~p至少有一半n是“费马证人”
3.在1~P中取k次数(n),用于素性测试,则pow(1/2,k)的概率表明p不是素数。如k=10,p不是素数的概率为0.0009765625
这是一个概率算法(一个产生正确结果有一定的概率的算法),算法准确度取决于测试的次数max_test
Python实现如下:
def prime_test(number, max_test):
# 0~max_test-1
for i in range(max_test):
# 1~number-1
if random.choice(range(1, number)) ** (number - 1) % number != 1:
return False
return True
if __name__ == "__main__":
print(prime_test(9999, 10))
测试结果:
PS:算法中当number很大时,如number=999979799744544,此时需要计算pow(n,number-1),计算量相当大,可以考虑使用快速求幂算法来计算。
4.快速求幂
"""
原理:
1、A**(2*M) == A**M**2
2、A**(2+M) == A**2 * A**M
计算A的p次幂
Float RaisePower(Float :A,Integer:P):
<使用第一个法则快速计算A**1,A**2,A**4,A**8,以此类推,知道A**N,N+1>P>
<利用这些A的幂,使用第二个法则计算A**p>
return A**p
一般地,将p表示为二进制形式,即P=2**a+2**b+2**c...+2**n,故A**P=A**(2**a) * A**(2**b) * A**(2**c) ...* A**(2**n)
"""
Python实现:
def raisePower(number, p) -> float:
power = 1
while p > 0:
# p & 1 等价于p%2==1
if p & 1:
power *= number # 用于计算最后的A**1或这说是A**(2**0)
# 右移
p >>= 1
number *= number # 计算 A**2,由A**2 * A**2 得到A**4,....得到A**N;例如A**7,因7b=111=4+2+1,故算法执行过程为,计算A**2,A**4,A**1
return power
if __name__ == "__main__":
print(raisePower(2, 8))
测试结果: