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

基于素数指数的大数压缩算法性能优化求助

问题

我希望通过素数指数实现数字压缩,采用基于连续素数序列、仅输出指数值来重构原数的方案。编写的Python函数在处理大数时效率极低,耗时可达数小时;扩充素数序列也未改善效果。需要优化现有代码的效率与结构,或提供适配任意大小数字的替代方案。

原代码

def get_primes(n):
    primes = []
    num = 2

    while len(primes) < n:
        is_prime = all(num % i != 0 for i in range(2, int(num**0.5) + 1))
        if is_prime:
            primes.append(num)
        num += 1

    return primes

def get_max_prime_amount(num):
    result = num // 3  # Use integer division for max_prime
    return result

def factorize_with_errors(original_number, primes, max_prime):
    error_count = 0
    soriginal_number = original_number
    tCount = 0
    PrimeArray = {}
    ExponentArray = {}

    for tPrimeCount in primes:
        tCount += 1
        PrimeArray[tCount] = tPrimeCount
        ExponentArray[tCount] = 0

    max_prime_number = PrimeArray[tCount]
    tCurrentPrimeCount = 1
    tFactorisation = False

    while not tFactorisation:
            if error_count == 99999999:
                breakpoint()

            tQuotient = gmpy2.mpfr(gmpy2.div(original_number,PrimeArray[tCurrentPrimeCount]))

        if tQuotient.is_integer():
            ExponentArray[tCurrentPrimeCount] += 1

            if tQuotient > max_prime_number:
                if tCurrentPrimeCount == max_prime:
                    tCurrentPrimeCount = 1
                    error_count += 1
                    original_number = int(tQuotient) - 1
                else:
                    original_number = int(tQuotient)
            elif tQuotient <= max_prime_number:
                if tQuotient == 1:
                    tFactorisation = True
                elif tQuotient in primes:
                    for tKey in PrimeArray:
                        if PrimeArray[tKey] == tQuotient:
                            ExponentArray[tKey] += 1
                            tFactorisation = True
                            break
                elif tQuotient not in primes:
                    tCurrentPrimeCount = 1
                    FinalFactorisation = False
                    while not FinalFactorisation:
                        tQuotientNew = tQuotient / PrimeArray[tCurrentPrimeCount]

                        if tQuotientNew == 1:
                            ExponentArray[tCurrentPrimeCount] += 1
                            tQuotient = tQuotientNew
                            tFactorisation = True
                            break
                        elif tQuotientNew.is_integer():
                            ExponentArray[tCurrentPrimeCount] += 1
                            tQuotient = tQuotientNew
                            break
                        else:
                            tCurrentPrimeCount += 1
                break

        elif not tQuotient.is_integer():
            if tCurrentPrimeCount == max_prime:
                tCurrentPrimeCount = 1
                error_count += 1
                soriginal_number -= 1
                original_number = soriginal_number
                for sKey in ExponentArray:
                    ExponentArray[sKey] = 0
            elif tCurrentPrimeCount < max_prime:
                tCurrentPrimeCount += 1

    ExponentArray["error_count"] = error_count
    return ExponentArray


original_number = 288684097887703
input_amount_len = len(str(original_number))
max_prime = get_max_prime_amount(input_amount_len)
primes = get_primes(max_prime)
result = factorize_with_errors(original_number, primes, max_prime)
print(result)
优化方案与替代方案

1. 素数生成优化

原素数生成函数采用暴力逐个判断,效率极低。替换为埃氏筛法,结合素数定理估算上限,大幅提升素数生成速度:

import math

def get_primes(n):
    if n == 0:
        return []
    # 估算第n个素数的上限,留有余量
    upper_bound = int(n * (math.log(n) + math.log(math.log(n)))) if n > 1 else 3
    sieve = [True] * (upper_bound + 1)
    sieve[0] = sieve[1] = False
    for i in range(2, int(math.isqrt(upper_bound)) + 1):
        if sieve[i]:
            sieve[i*i : upper_bound+1 : i] = [False]*len(sieve[i*i : upper_bound+1 : i])
    primes = [i for i, is_p in enumerate(sieve) if is_p]
    # 若估算上限不足,动态扩展
    while len(primes) < n:
        upper_bound *= 2
        sieve = [True] * (upper_bound + 1)
        sieve[0] = sieve[1] = False
        for p in primes:
            start = max(p*p, ((primes[-1] // p) + 1)*p)
            sieve[start : upper_bound+1 : p] = [False]*len(sieve[start : upper_bound+1 : p])
        primes.extend([i for i in range(primes[-1]+1, upper_bound+1) if sieve[i]])
    return primes[:n]

2. 因式分解逻辑重构

原函数逻辑混乱,存在浮点数精度问题与低效查找。以下优化实现基于整数运算,避免修改原数:

import gmpy2

def factorize(num, primes):
    num = gmpy2.mpz(num)
    # 构建素数到索引的映射,实现O(1)查找
    prime_index = {p: idx for idx, p in enumerate(primes, 1)}
    max_idx = len(primes)
    exponents = [0] * (max_idx + 1)  # 索引从1开始对应素数序列

    for idx, p in enumerate(primes, 1):
        if p*p > num:
            break
        while num % p == 0:
            exponents[idx] += 1
            num = num // p
    # 处理剩余的大素数
    if num > 1:
        if num in prime_index:
            exponents[prime_index[num]] += 1
        else:
            raise ValueError(f"剩余数 {num} 不在提供的素数序列中,无法分解")
    # 转换为原输出格式的字典
    exponent_dict = {i: exponents[i] for i in range(1, max_idx+1)}
    exponent_dict["error_count"] = 0
    return exponent_dict

3. 整体流程优化

原get_max_prime_amount逻辑缺乏依据,改用素数定理估算所需素数数量,确保覆盖原数所有素因数:

def estimate_required_primes(num):
    num = gmpy2.mpz(num)
    if num == 1:
        return 1
    max_p = num
    # 素数定理反向估算所需素数数量,留有余量
    pi = int(max_p / math.log(max_p)) if max_p > 2 else 1
    return pi + int(math.sqrt(pi))

# 使用示例
original_number = 288684097887703
required_primes_count = estimate_required_primes(original_number)
primes = get_primes(required_primes_count)
result = factorize(original_number, primes)
print(result)

4. 替代方案:适配超大数的因式分解

对于超大数,试除法效率不足,可采用Pollard's Rho算法进行快速因式分解:

import random
import gmpy2

def pollards_rho(n):
    if n % 2 == 0:
        return 2
    if n % 3 == 0:
        return 3
    if n % 5 == 0:
        return 5
    while True:
        c = gmpy2.mpz(random.randint(1, n-1))
        f = lambda x: (gmpy2.powmod(x, 2, n) + c) % n
        x, y, d = 2, 2, 1
        while d == 1:
            x = f(x)
            y = f(f(y))
            d = gmpy2.gcd(abs(x-y), n)
        if d != n:
            return d

def factorize_large(n):
    factors = {}
    def _factorize(n):
        if n == 1:
            return
        if gmpy2.is_prime(n):
            factors[n] = factors.get(n, 0) + 1
            return
        d = pollards_rho(n)
        _factorize(d)
        _factorize(n//d)
    _factorize(gmpy2.mpz(n))
    return factors

分解得到因数后,再映射到连续素数的指数序列即可。

内容的提问来源于stack exchange,提问作者Tone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:39:51