簡體   English   中英

是否可以在python中快速將非常大的int轉換為字符串

[英]Is it possible to convert a really large int to a string quickly in python

我正在構建一個生成大量整數的加密程序。它看起來像這樣:

a = plaintextOrd**bigNumber

當我做

a = str(a)

需要28分鍾以上。

有沒有辦法比使用內置的 str() 函數更快地轉換這樣的整數?

我需要它是一個字符串的原因是因為這里的這個函數:

def divideStringIntoParts(parts,string):
    parts = int(parts)
    a = len(string)//parts

    new = []
    firstTime = True
    secondTime = True
    for i in range(parts):
        if firstTime:
            new.append(string[:a])
            firstTime = False
        elif secondTime:
            new.append(string[a:a+a])
            secondTime = False
        else:
            new.append(string[a*i:a*(i+1)])

    string2 = ""
    for i in new:
        for i in i:
            string2 += i

    if len(string2) - len(string) != 0:
        lettersNeeded = len(string) - len(string2)
        for i in range(lettersNeeded):
            new[-1] += string[len(string2) + i] 

    return new

您在評論中寫道,您希望以十進制格式獲取整數的長度。 您不需要將此整數轉換為字符串,您可以使用“常用對數”代替:

import math
math.ceil(math.log(a, 10))

此外,如果您知道:

a = plaintextOrd**bigNumber

然后math.log(a, 10)等於math.log(plaintextOrd, 10) * bigNumber ,計算時間不應超過幾毫秒:

>>> plaintextOrd = 12345
>>> bigNumber = 67890
>>> a = plaintextOrd**bigNumber
>>> len(str(a))
277772
>>> import math
>>> math.ceil(math.log(a, 10))
277772
>>> math.ceil(math.log(plaintextOrd, 10) * bigNumber)
277772

即使a不適合您的硬盤驅動器,它也應該可以工作:

>>> math.ceil(math.log(123456789, 10) * 123456789012345678901234567890)
998952457326621672529828249600

正如@kaya3 所提到的,Python 標准浮點數不夠精確,無法描述如此大的數字的確切長度。

您可以使用mpmath (任意精度浮點運算)來獲得所需精度的結果:

>>> from mpmath import mp
>>> mp.dps = 1000
>>> mp.ceil(mp.log(123456789, 10) * mp.mpf('123456789012345678901234567890'))
mpf('998952457326621684655868656199.0')

關於“我需要它來實現此功能”的一些快速說明。

  • 您不需要第一個/第二個邏輯:
    • [:a] == [a*0:a*(0+1)]
    • [a:a+a] == [a*1:a*(1+1)]

所以我們有

    new = []
    for i in range(parts):
        new.append(string[a*i:a*(i+1)])

或者只是new = [string[a*i:a*(i+1)] for i in range(parts)]

請注意,您已經悄悄地丟棄了最后一個len(string) % parts字符。

在你的第二個循環中,你用for i in i遮蔽i ,這碰巧工作但很尷尬和危險。 它也可以替換為string2 = ''.join(new) ,這意味着您可以只執行string2 = string[:-(len(string) % parts)]

然后查看字符串的長度是否相同,然后將額外的字母添加到最后一個列表的末尾。 這有點令人驚訝,例如你會

>>> divideStringIntoParts(3, '0123456789a')
['012', '345', '6789a']

當大多數算法會產生有利於均勻分布和早期元素的東西時,例如:

>>> divideStringIntoParts(3, '0123456789a')
['0124', '4567', '89a']

無論如何,我們看到您在這里根本不關心字符串的值,只關心它有多少位數字。 因此,您可以按如下方式重寫您的函數。

def divide_number_into_parts(number, parts):
    '''
    >>> divide_number_into_parts(12345678901, 3)
    [123, 456, 78901]
    '''
    total_digits = math.ceil(math.log(number + 1, 10))
    part_digits = total_digits // parts
    extra_digits = total_digits % parts

    remaining = number
    results = []
    for i in range(parts):
        to_take = part_digits
        if i == 0:
            to_take += extra_digits
        digits, remaining = take_digits(remaining, to_take)
        results.append(digits)
    # Reverse results, since we go from the end to the beginning
    return results[::-1]


def take_digits(number, digits):
    '''
    Removes the last <digits> digits from number.
    Returns those digits along with the remainder, e.g.:
    >>> take_digits(12345, 2)
    (45, 123)
    '''
    mod = 10 ** digits
    return number % mod, number // mod

這應該非常快,因為它完全避免了字符串。 如果您願意,您可以在最后將其更改為字符串,這可能會或可能不會從這里的其他答案中受益,具體取決於您的塊大小。

GMPY2提供了比函數 str 更快的 int 到 str 的轉換

下面示例的來源

import time
from gmpy2 import mpz

# Test number (Large)
x = 123456789**12345

# int to str using Python str()
start = time.time()
python_str = str(x)
end = time.time()

print('str conversion time {0:.4f} seconds'.format(end - start))

# int to str using GMPY2 module
start = time.time()
r = mpz(x)
gmpy2_str = r.digits()
end = time.time()

print('GMPY2 conversion time {0:.4f} seconds'.format(end - start))
print('Length of 123456789**12345 is: {:,}'.format(len(python_str)))
print('str result == GMPY2 result {}'.format(python_str==gmpy2_str))

結果(GMPY2 在測試中快了 12 倍)

str conversion time 0.3820 seconds
GMPY2 conversion time 0.0310 seconds
Length of 123456789**12345 is: 99,890
str result == GMPY2 result True

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM