You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确在Python中实现费马因式分解算法以获取完整质因数?

如何正确在Python中实现费马因式分解算法以获取完整质因数?

嘿,我帮你分析下代码出错的原因,再给你一套修复后的可靠实现~

首先,你的费马因式分解代码里有两个关键问题,直接导致了错误的质因数输出:

1. 初始值a的计算逻辑错误

费马分解的核心是从大于等于√n的最小整数开始找a,但你用了int(n ** 0.5 + 0.5),这其实是对√n做四舍五入,而非向上取整。比如对于质数17,√17≈4.123,四舍五入后得到4,但正确的起始a应该是5(因为4²=16<17,5²=25>17)。

这个错误直接导致代码对某些质数(比如17)错误分解出3和5(3×5=15≠17),递归下去自然会引入完全无关的因数,比如你例子里出现的2。

2. 浮点数精度带来的误差

你用b2**0.5计算平方根,当b2很大时,浮点数精度有限,无法精确表示大整数的平方根,转成int后会得到错误值,进而分解出错误的因数对。


修复后的完整实现

我调整了代码,解决了上述问题,还加入了通用素性测试(代替预生成质数集合,能处理更大的数),以及自动处理2的因数:

第一步:实现可靠的素性测试(Miller-Rabin算法)

这个算法能高效判断一个数是否为质数,比预生成质数集合灵活得多:

import math

def is_prime(n):
    if n <= 1:
        return False
    elif n <= 3:
        return True
    elif n % 2 == 0:
        return False
    # 将n-1分解为d*2^s的形式
    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1
    # 对于n < 2^64,这些底数足够保证正确性
    bases = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
    for a in bases:
        if a >= n:
            continue
        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            continue
        for _ in range(s - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
    return True

第二步:修复费马因式分解函数

def FermatFactor(n):
    factors = []
    # 先处理所有2的因数(也可以用位运算优化:while n & 1 == 0)
    while n % 2 == 0:
        factors.append(2)
        n = n // 2
    if n == 1:
        return factors
    # 递归终止条件:当前数是质数
    if is_prime(n):
        factors.append(n)
        return factors
    # 正确计算初始a:大于等于√n的最小整数
    a = math.isqrt(n)
    if a * a == n:
        # 如果是平方数,递归分解平方根
        sub_factors = FermatFactor(a)
        factors.extend(sub_factors * 2)
        return factors
    a += 1  # 若a² <n,需要加1得到第一个大于√n的整数
    # 寻找满足a² -n是完全平方数的a
    while True:
        b2 = a * a - n
        b = math.isqrt(b2)
        if b * b == b2:
            break
        a += 1
    # 分解得到两个因数,递归处理
    factor1 = a - b
    factor2 = a + b
    factors.extend(FermatFactor(factor1))
    factors.extend(FermatFactor(factor2))
    return factors

测试修复后的代码

现在再跑你之前出错的案例:

# 测试错误案例1
print(FermatFactor(5 * 53 * 163))  # 输出 [5, 53, 163](顺序可能不同)
# 测试错误案例2
print(FermatFactor(3 * 5 * 73 * 283))  # 输出 [3,5,73,283]
# 测试错误案例3
print(FermatFactor(3 * 11 * 29 * 71 * 137))  # 输出 [3,11,29,71,137]

所有结果都会是正确的质因数列表,顺序可能不同,但乘积和原数一致。


额外说明

  • 费马分解最适合分解两个相近质数的乘积(半质数),对于相差很大的质数,效率不如试除法,但递归逻辑已经自动处理了这种情况——如果分解出的因数可以继续分解,就会递归下去。
  • 加入Miller-Rabin素性测试后,不需要依赖预生成的质数集合,能处理更大的数(只要Python支持大整数就行)。

备注:内容来源于stack exchange,提问作者Ξένη Γήινος

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 14:18:05