1、大素数
在加密相关算法中,常需要快速生成一些大素数。请编写一个程序,在给定的时间内(譬如3秒)生成一个尽可能大的素数,同时给出其位数。
思路:
说实话一开始看到这道题目的时候是有点懵的,生成一个尽可能大的素数,那么多大才算是最大?不同于c++,有一个数据类型约束着,在python里实在想不到数的边界是什么.唯一的线索就是限定的3s.
突然想到了,我可以试着生成一个尽量大的数,然后判断它是不是素数就可以了,如果不是的话就就在它附近加一再找找那肯定会有素数的!
那么新问题又来了,怎么生成一个尽可能大的数呢?又考虑到时间是有限制的,所以我想到了可以使用位运算来快速得到一个大数,但由于对3s这个时间对于我们的电脑来说是一个什么概念不太懂,于是就从1开始给它向左移位,移动一位相当于乘2.然后把生成的数进行素数判断,如果是素数就记录下来,同时把移动的位数增加,以获得一个更大的位数,如果生成的数不是素数就尝试加一来再进行判断,总会加到素数的(笑~).而移动位数的增加为了更具有随机性,我每次给他加上1到100的数字,想:移动的位数这样一直加上去总会产生一个很大的数,也就符合我们的目的了.
但问题还有,那就是怎么进行素数的判断.说到这个问题可能大家脑子里都浮现出了一些很经典的做法,比如通过for循环来进行相除,只要没有被除尽就是素数.但很遗憾,这在这道题中看来不是很行得通.因为那样的时间效率太低了,每次都用循环来一次次的找太慢了.这可咋办?(当然是选择问问度娘了)好家伙,一查发现判断素数有一个算法,叫做米勒罗宾也就是Miller Rabin这个人搞的一个验证素数的算法,虽然对于具体的数学逻辑不是很懂(咱毕竟不是学数学的对吧),直接拿来用就完事了.好像是通过一定次数的米勒罗宾算法之后还成立的就是素数,大概这个意思.(可能不是)
然后判断素数这个问题解决了,剩下的问题就只有时间了,要怎么来限定时间呢?我是通过这种方式来约束的:即一开始先把程序开始的时间使用time第三方库中的time方法记录下来为start,然后在程序进行素数判断的时候进行判断,一旦发现当前的时间(也是通过time方法来获取)减去start大于等于3s时停止程序,同时把之前记录下的最大素数和它的位数给输出来.
代码区:
import random
import time
def miller_rabin(p):
if p == 1:
return False
if p == 2:
return True
if p % 2 == 0:
return False
m, k, = p - 1, 0
while m % 2 == 0:
m, k = m // 2, k + 1
a = random.randint(2, p - 1)
x = pow(a, m, p)
if x == 1 or x == p - 1:
return True
while k > 1:
x = pow(x, 2, p)
if x == 1:
return False
if x == p - 1:
return True
k = k - 1
return False
def is_prime(p, r=5):
for _ in range(r):
if not miller_rabin(p):
return False
return True
def main():
num_max = 0
c = 1
end = 0
start = time.time() # 记录当前的时间保存为start
while True:
num = 1 << c # 获取尽可能大的数
while not is_prime(num):
num = num + 1 # +1继续进行素数判断
if time.time() - start >= 3:# 当时间到了以后结束程序
print('--------已用时间:', end - start, 's----------')
return num_max
c += random.randint(1, 100)
num_max = max(num_max, num)
end = time.time()
number = main()
print('--------位数为:', len(str(number)), '----------------------------')
print('素数为:', number)
2、梅森素数
梅森素数由梅森数而来。
所谓梅森数,是指形如2p-1的一类数,其中指数p是素数,常记为Mp 。如果梅森数是素数,就称为梅森素数。
用因式分解法可以证明,若2n-1是素数,则指数n也是素数;反之,当n是素数时,2**n-1(即Mp)却未必是素数。前几个较小的梅森数大都是素数,然而梅森数越大,梅森素数也就越难出现。
自梅森提出其断言后,人们发现的已知最大素数几乎都是梅森素数,因此寻找新的梅森素数的历程也就几乎等同于寻找新的最大素数的历程。
梅森素数的探寻难度极大,它不仅需要高深的理论和纯熟的技巧,而且需要进行艰苦的计算。
请编写一个程序,在给定的时间内(譬如3秒)生成尽可能多的梅森素数。
思路:
这道题可以说是上一题的兄弟姐妹,其实上一题做了之后这道题也就可以说是做出来了.同样是关于素数的,只不过上一题是要我们在3s内输出一个尽可能大的素数,而这道题是要我们输出尽可能多的梅森素数.
所谓梅森素数我们可以这么处理,从2开始找素数,每次都加一,然后进行素数判断,符合梅森素数条件的素数就把它输出同时计数器加一.最后在时间结束的时候就停止运行程序.
而其他的部分和上一题是一致的.
代码区:
import random
import time
def miller_rabin(p):
if p == 1:
return False
if p == 2:
return True
if p % 2 == 0:
return False
m, k, = p - 1, 0
while m % 2 == 0:
m, k = m // 2, k + 1
a = random.randint(2, p - 1)
x = pow(a, m, p)
if x == 1 or x == p - 1:
return True
while k > 1:
x = pow(x, 2, p)
if x == 1:
return False
if x == p - 1:
return True
k = k - 1
return False
def is_prime(p, r=5):
for _ in range(r):
if not miller_rabin(p):
return False
return True
def main():
end = 0
start = time.time()
num = 1
count = 0
while True:
num += 1
while not is_prime(num):
num = num + 1
p = 2 ** num - 1
if is_prime(p):
if time.time() - start >= 3:
print('--------已用时间:', end - start, 's----------')
return count
print(p)
count += 1
end = time.time()
cnt = main()
print('找到了', cnt, '个梅森素数')
3、定积分
结合定积分定义,写一个函数integral,用于求可积函数f在区间[a,b]上的定积分。后测试下此函数,譬如用此函数求单位圆面积。(练习用下:列表推导式,参数默认值,lambda函数等语法或用法)
思路:
需要计算定积分,我们需要引入sympy这个第三方库.因为我们需要用到x这个变量,所以我们要先引入x变量.
由于是要求圆的面积,所以这个对应的被积函数是sqrt(r^2 - x ^2).而明确了这一点之后,就可以使用sympy中的integrate方法,这个方法的参数是一个函数,和两个积分的上下限.
我们先求四分之一的圆面积,这样积分下限为0,积分上限为半径.最后再乘4就可以了.详细代码见下方.
代码区:
import sympy
from sympy.abc import x
def integral(function, b, a=0):
return sympy.integrate(function, (x, a, b))
if __name__ == '__main__':
r = int(input('请输入半径:'))
fx = sympy.sqrt(r ** 2 - x ** 2)
circle = lambda fa, ra: 4 * integral(fa, ra)
print('圆面积为:', circle(fx, r))
新手上路,有错请指正;