算法与数据结构:数值算法

  1. 寻找素数因子

         寻找一个数的素因子的最显而易见的办法是:尝试将这个数用比其小大于等于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))
测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值