Python 快速将整数转换为字符串

3
我正在使用Python解决大规模的阶乘计算问题,发现在计算完毕后将结果转换为字符串并保存至文件时需要相同的时间。我已经尝试了使用通用方法a = str(a)进行整数转换,但感觉有更好的方式,如使用缓冲或库。
例如:
计算100,000的阶乘= 456,574位数字
计算时间:6.36秒
转换时间:5.20秒
如果您有任何建议/解决方案,请告诉我!任何帮助都会有所裨益。
import time

factorial = 1

print(" ")

one = int(input("lower  = "))
two = int(input("higher = "))

start = time.time()

for x in range(one,two + 1):
        factorial = factorial * two
        two = two - 1

end = time.time()

print("DONE! ")
print(end - start, "Seconds to compute")

start = time.time()

factorial = str(factorial)

f = open('Ans_1.txt','w')
f.write(factorial)
f.close()

end = time.time()

print(end - start, "Seconds to convert and save")

print(len(factorial), "Digets")

1
我们需要看到您的代码。就将int转换为str而言,str(int)是最快的。但是,您的阶乘逻辑肯定有改进的空间。 - Moinuddin Quadri
@MoinuddinQuadri 我不确定他的阶乘逻辑能够提高多少。我使用 math.factorial(100000) 时得到了类似的运行时间。 - user3483203
1
如果OP正在使用math.factorial,那么我怀疑在Python 2.7中无法做任何事情。在Python 3中,它会比较快。这里有一个讨论可能会引起兴趣为什么Python 2.x中的math.factorial比3.x慢得多? - Moinuddin Quadri
我认为没有更快的方法将其保存到字符串中,因为那是内置的方法。 @chrisz:在Python 3中,math.factorial(100000)比使用此代码快约20倍。我已经尝试过30多种不同的算法,试图获得比过去的“数学”更快的时间,最终放弃了。如果OP想要使这段代码更快,我建议尽量减少涉及大数字的步骤。存储大数字需要更多时间来转换成小数字。 - 1313e
只是试试使用 PyPy :D - RaminNietzsche
使用适当的精度与十进制模块。这样做会更快,因为十进制数在内部存储为字符串,所以可以跳过转换过程。 - user2341726
3个回答

6

您可以尝试使用gmpy2 的 x.digits([base]) 方法。

import time
from gmpy2 import mpz


x = 123456789**12345

start = time.time()
python_str = str(x)
end = time.time()
print(end - start, "Python conversion time")

r = mpz(x)
start = time.time()
gmpy2_str = r.digits()
end = time.time()
print(end-start, "gmpy2 conversion time")

上面的测试输出:

1.0336394309997559 Python 转换时间

0.03306150436401367 gmpy2 转换时间


1
gmpy2 还具有非常快的阶乘函数。在我的计算机上,str(math.factorial(100000)) 需要约 2.5 秒钟。str(gmpy2.fac(100000)) 只需要约 0.03 秒钟。而且 str(gmpy2.fac(1000000)) 需要约 0.7 秒钟。 - casevh

1

这段代码更快(但还不够快! :D)

结果:

╔═══╦════════════╦═════════════╦══════════════╦═══════════════════╗
║   ║ Count      ║ Compute(s)  ║  Convert(s)  ║  M.T Convert(s)   ║
╠═══╬════════════╬═════════════╬══════════════╬═══════════════════╣
║ 1 ║ 100,000    ║    2.68     ║     3.85     ║        2.81       ║
║ 2 ║ 250,000    ║   21.17     ║     39.83    ║       21.09       ║
╚═══╩════════════╩═════════════╩══════════════╩═══════════════════╝

无论如何,我认为您可以通过多线程更快地完成它。

import time import math import threading

res_dict = {}

def int_str(threadID, each_thread, max_thread):
    if threadID == 1 :
        res_dict[threadID] = (str(factorial // 10 ** (each_thread * (max_thread - 1))))
    elif threadID == max_thread:
        res_dict[threadID] = (str(int(factorial % 10 ** (each_thread * 1))))
    else: 
        tmp = (factorial % 10 ** (each_thread * (max_thread - threadID + 1))) // 10 ** (each_thread * (max_thread - threadID))
        pre = "0" * ((digits // max_thread) - (math.floor(math.log10(tmp))+1))
        res_dict[threadID] = (pre + str(int(tmp)))

factorial = 1

print(" ")

def fact(a,b):
    if b == 1:
        return 1
    else:
        return a * fact(a,b-1)

one = int(input("lower  = "))
two = int(input("higher = "))

start = time.time()

for x in range(one,two + 1):
        factorial = factorial * two
        two = two - 1

end = time.time()

print("DONE! ")
print(end - start, "Seconds to compute")


start = time.time()

digits = math.floor(math.log10(factorial))+1

max_thread      = 3
each_thread     = digits // max_thread

tr = []

for item in range(1, max_thread + 1):
    t = threading.Thread(target=int_str, args=(item, each_thread, max_thread))
    t.start()
    tr.append(t)


for item in tr:
    item.join()

last_res = ''

for item in sorted(res_dict):
    if item != max_thread:
        last_res += res_dict[item]
    else:
        last_res += ("0" * (digits - len(last_res) - len(res_dict[item]))) + res_dict[item]


f = open('Ans_2.txt','w')
f.write(last_res)
f.close()


end = time.time()
print(end - start, "Seconds to convert and save")

print(digits, "Digets")

更新:

只需使用 pypy 运行您的代码,它非常快速!

╔═══╦════════════╦═════════════╦══════════════╦═══════════════════╗
║   ║ Count      ║ Compute(s)  ║  Convert(s)  ║ pypy Convert(s)   ║
╠═══╬════════════╬═════════════╬══════════════╬═══════════════════╣
║ 1 ║ 100,000    ║    2.98     ║     3.85     ║        0.79       ║
║ 2 ║ 250,000    ║   25.83     ║     39.83    ║        7.17       ║
╚═══╩════════════╩═════════════╩══════════════╩═══════════════════╝

0

int().__str__()str(int)更快,因为str()需要查找它正在转换的类型。

import time
    
start=time.time()
x1=[x.__str__() for x in range(10000)]
print(f"__str__: {time.time()-start}")

start=time.time()
x2=[str(x) for x in range(10000)]
print(f"str: {time.time()-start}")

print(x1==x2)

>>>__str__: 0.005000591278076172
>>>str: 0.006000518798828125
>>>True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接