素数转圈问题1.1

        前言

        先前针对“在一平面直角坐标系上小云兮在遛狗狗,一开始的运动方向为x轴正方向。现记其走过的路程为s,当s为素数时,遛狗的前进方向顺时针旋转90度。现问当总路程x等于某一输入值时,其在x轴或y轴方向上所达到的最遥远两端的距离”这一问题粗浅地写了素数转圈问题1.0来解决。但经过实际测试发现,在总路程x越来越大,例如令x=100000(十万)时,时间戳的计算结果已经达到了60.54499888420105s,已经在一定程度上失去了其实用性,故本文素数转圈问题1.1主要着手优化该程序在面对较大数据的处理速度问题。

        问题分析

        经过对原代码的逐一分析,可以得到原代码在“第一步:收集x以内的素数”模块上直截粗暴,采用的是将所有小于输入值的正整数逐个除输入值,通过舍去能被整除的数来判断的,此过程会占用大量内存,低效缓慢:

#原代码
def is_prime(num,list):
    #判断素数并收集到list
    if num==0 or num==1:
        return()
    for factor in range(2,num):
        if num%factor==0:
            return()
    list.append(num)
    return()

        在“第二步:计算每段的长度”上代码稍有冗长,且没有必要额外定义函数:

#原代码
def delta_lists(n,list1,list2,delta_list):
    #两个列表中数据逐项做差,并收集到delta_list
    for factor in range(n):
        m=list1[factor]-list2[factor]
        delta_list.append(m)
    return()

        接下来就是要先解决这些核心问题。

        优化一:收集x以内的素数

        这里采用除去特例的情况下,优先排除被2,3整除的数据,在通过分析因子,并提前跳过3的倍数,来化简运算,代码如下:

def is_prime(n,list):
    if n<=1:  # 0和1不是质数
        return ()
    elif n==2 or n==3:  # 2和3是特例,它们是质数
        list.append(n)
    elif n%2==0 or n%3==0:  # 质数一定不能被2或3整除
        return ()
    i=5
    while i*i<=n:  # 验证到i^2是否大于n即可,因为后续的因子都是6k±1的形式
        if n%i==0 or n%(i+2)==0:
            return ()
        i+=6  # 提前跳过3的倍数
    list.append(n)
    return ()

        优化二:计算每段的长度

        摒弃定义函数的冗余做法,选择在列表中运算,并直接放到主体部分去,代码如下:

delta_list=[a-b for a,b in zip(list1, list2)]

       也顺带将变量赋值写的方便看一些,代码如下:

#原代码
x=0
y=0
xmax=0
xmin=0
ymax=0
ymin=0
#现在
x,y,xmax,xmin,ymax,ymin=0,0,0,0,0,0

       全部代码

        素数转圈问题1.1全部代码如下:

def is_prime(n,list):
    if n<=1:  # 0和1不是质数
        return ()
    elif n==2 or n==3:  # 2和3是特例,它们是质数
        list.append(n)
    elif n%2==0 or n%3==0:  # 质数一定不能被2或3整除
        return ()
    i=5
    while i*i<=n:  # 验证到i^2是否大于n即可,因为后续的因子都是6k±1的形式
        if n%i==0 or n%(i+2)==0:
            return ()
        i+=6  # 提前跳过3的倍数
    list.append(n)
    return ()



def extreme_value(max,min,x):
    #极值
    if x>=max:
        max=x
    if x<=min:
        min=x
    return(max,min)



def divide_xy_ans(n,delta_list):
    #区分x,y方向位移并计算
    x,y,xmax,xmin,ymax,ymin=0,0,0,0,0,0
    for factor in range(n):
        if factor%4==0:
            x+=delta_list[factor]
            xmax,xmin=extreme_value(xmax,xmin,x)
            continue
        elif factor%4==1:
            y-=delta_list[factor]
            ymax,ymin=extreme_value(ymax,ymin,y)
            continue
        elif factor%4==2:
            x-=delta_list[factor]
            xmax,xmin=extreme_value(xmax,xmin,x)
            continue
        elif factor%4==3:
            y+=delta_list[factor]
            ymax,ymin=extreme_value(ymax,ymin,y)
    xans=xmax-xmin
    yans=ymax-ymin
    return(xans,yans)



#主体部分
print('问题:在一平面直角坐标系上小云兮在遛狗狗,一开始的运动方向为x轴正方向。\
现记其走过的路程为s,当s为素数时,遛狗的前进方向顺时针旋转90度。\
现问当总路程x等于某一输入值时,其在x轴或y轴方向上所达到的最遥远两端的距离。')
list1=[]
delta_list=[]
num=int(input("请输入移动总路程:"))
if num==0 or num==1 or num==2:
    xans=num
    yans=0
else:
    for factor in range(num):
        is_prime(factor,list1)
    list2=list1.copy()
    list2.insert(0,0)
    n=len(list1)
    delta_list=[a-b for a,b in zip(list1, list2)]
    if num not in list1:
        delta_list.append(num-list1[n-1])
    n_final=len(delta_list)
    xans,yans=divide_xy_ans(n_final,delta_list)
    ans=max(xans,yans) 
print('水平方向的极差=',xans,'竖直方向的极差=',yans,'最大的极差=',ans)

        测试优化结果

        程序在优化之后效率有了显著提升,对于同样的令x=100000(十万),素数转圈问题1.1的时间戳计算结果为0.14970755577087402s,而对于更大数量级的x=1000000(一百万),时间戳的计算结果为3.7286486625671387s,比素数转圈问题1.0快了许多。

        小结

        这一次优化了程序的运算效率问题,有明显的效果。但在代码的其他方面仍有可优化之处,期待下次优化。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值