使用Python 3快速计算实数巨大整数的基数3值

phd*_*upA 5 python math performance

我们有很多像(10**1500000)+1,并希望将其转换为基数3.下面是我们用普通Python发现的最快方式运行代码(不使用numpy或CAS库).

如何加速基础转换(到基数3)的性能?

我们想知道如何通过以下两种方式完成此操作:

  1. 仅使用Python 3的内置函数(没有numpy)?
  2. 在普通的Python 3程序中使用numpy(或另一个CAS库)?

非常欢迎任何帮助.这是我们目前的代码:

#### --- Convert a huge integer to base 3 --- ####

# Convert decimal number n to a sequence of list elements
# with integer values in the range 0 to base-1.
# With divmod, it's ca. 1/3 faster than using n%b and then n//=b.
def numberToBase(n, b):
    digits = []
    while n:
        n, rem = divmod(n, b)
        digits.append(rem)
    return digits[::-1]

# Step 2: Convert given integer to another base
# With convsteps == 3, it's about 50-100 times faster than
# with with convsteps == 1, where numberToBase() is called only once.
def step2(n, b, convsteps):
    nList = []
    if convsteps == 3:  # Here the conversion is done in 3 steps
        expos = 10000, 300
        base_a = b ** expos[0]
        base_b = b ** expos[1]
        nList1 = numberToBase(n, base_a)  # time killer in this part
        nList2 = [numberToBase(ll, base_b) for ll in nList1]
        nList3 = [numberToBase(mm, b) for ll in nList2 for mm in ll]
        nList = [mm for ll in nList3 for mm in ll]
    else: # Do conversion in one bulk
        nList = numberToBase(n, b)  # that's the time killer in this part
    return nList


if __name__ == '__main__':

    int_value = (10**1500000)+1  # sample huge numbers
                          # expected begin: [2, 2, 0, 1, 1, 1, 1, 0, 2, 0]
                          # expected time: 4 min with convsteps=3
    base = 3

    # Convert int_value to list of numbers of given base
    # -- two variants of step2() using different convsteps params
    numList = step2(int_value, base, convsteps=1)
    print('   3-1: numList begin:', numList[:10])

    # A value of '3' for the parameter "convsteps" makes
    # step2() much faster than a value of '1'
    numList = step2(int_value, base, convsteps=3)
    print('   3-3: numList begin:', numList[:10])
Run Code Online (Sandbox Code Playgroud)

如何尽可能快地计算整数的基数3值,该整数是作为一个巨大的十进制数字序列(超过一百万)给出的? 是一个类似的问题,在基本转换之前还有一些步骤.在这里的这个问题中,我们专注于那个在很长一段时间内消耗的部分,而我们还没有得到答案.

此外,在将基数为10的数字转换为基数为3的数字时,未处理巨大数字的性能方面.

Mar*_*som 6

这是一种convsteps通过在每次调用时使用基本平方递增来扩展解决方案的方法.删除前导零需要一些额外的工作.

def number_to_base(n, b):
    if n < b:
        return [n]
    else:
        digits = [d for x in number_to_base(n, b*b) for d in divmod(x, b)]
        return digits if digits[0] else digits[1:]
Run Code Online (Sandbox Code Playgroud)

我的快速计时测试显示它step2与误差范围内的相同.但它更简单,可能有更少的错误.

  • 只是想添加,我做了一些基准测试,对于基数10,在~`n = 10**1000000`之后,这个函数开始优于`str(n)`,最终归结为`long_to_decimal_string_internal()`使用TAOCP,Knuth - Vol.2个教派 4.4方法1b.这包括`"".join(map(str,...))`的时间.对于'n = 10**10000000`,它的速度是内置转换的2倍.在Windows 10上测试Python 3.6.4. (2认同)