虽然@pranav-hosangadi 提供的答案很棒,但我赞同他的说法,即会有不同。
我想指出的是,对于一组输入来说,“最好/最快”的解决方案可能并不是对所有输入都是最好的。在寻找更好/更快的解决方案时,了解输入数据的“外观”可能很重要。
对于@pranav-hosangadi 选择的输入(非常大的数字字符串),他的concatenate3() 显然是最快的。考虑到问题是关于确定“大”数字的某些内容,他们对输入的选择似乎非常合理。
但是,如果定义大数的问题是最多十位数的问题(在某些情况下仍然很大),那么他们的 concatenate3() 方法实际上比前两种方法和第四种方法慢:
def concatenate4(num1, num2):
return int(f"{num1}{num2}")
比这三个都快(至少在我的笔记本电脑上)。
同样重要的是,这个新的concatenate4() 并不是普遍更快,并且对于@pranav-hosangadi 使用的范围内的输入,它的性能“很差”。而他们的concatenate3() 则粉碎了其他人。
import timeit
import math
def concatenate1(num1, num2):
num1 = str(num1)
num2 = str(num2)
num1 += num2
return int(num1)
def concatenate2(num1, num2):
digits = len(str(num2))
num1 = num1 * (10**digits)
num1 += num2
return num1
def concatenate3(num1, num2):
l = math.log10(num2)
digits = int(l) + 1
num1 = num1 * (10**digits)
num1 += num2
return num1
def concatenate4(num1, num2):
return int(f"{num1}{num2}")
num1 = int("1"*10)
num2 = int("2"*10)
t1 = timeit.timeit('concatenate1(num1, num2)', 'from __main__ import concatenate1, num1, num2', number=1000)
t2 = timeit.timeit('concatenate2(num1, num2)', 'from __main__ import concatenate2, num1, num2', number=1000)
t3 = timeit.timeit('concatenate3(num1, num2)', 'from __main__ import concatenate3, num1, num2', number=1000)
t4 = timeit.timeit('concatenate4(num1, num2)', 'from __main__ import concatenate4, num1, num2', number=1000)
print("t1=", 100_000*t1, "; t2=", 100_000*t2, "; t3=", 100_000*t3, "; t4=", 100_000*t4)
结果:
t1= 63.25999999999971 ; t2= 58.6299999999998 ; t3= 64.32999999999994 ; t4= 40.889999999999674
在我的笔记本电脑上,concatinate3() 只有在组合每个超过 35 位的数字时才会变得最快。
让我们尝试回答原因:
让我们来看看concatenate3() 和concatenate4() 的各个步骤的大致时间安排。请注意,各个步骤的真实成本被函数调用开销所掩盖,因此是粗略的近似值,但它们仍然基于真实的时序测试并说明了一个有趣的点。
对于超过 1000 次运行的 10 位数字concatenate3():
def concatenate3(num1, num2): # 59 time units (accurate)
l = math.log10(num2) # 18 time units
digits = int(l) + 1 # 14 time units
num1 = num1 * (10**digits) # 12 time units
num1 += num2 # 7 time units
return num1
对于超过 1000 次运行的 10 位数字concatenate4():
def concatenate4(num1, num2): # 45 time units (accurate)
tmp = f"{num1}{num2}" # 30 time units
tmp = int(tmp) # 20 time units
return tmp
对于超过 1000 次运行的 1000 位数字concatenate3():
def concatenate3(num1, num2): # 1400 time units (accurate)
l = math.log10(num2) # 23 time units
digits = int(l) + 1 # 15 time units
num1 = num1 * (10**digits) # 1341 time units
num1 += num2 # 2119 time units
return num1
对于超过 1000 次运行的 1000 位数字concatenate4():
def concatenate4(num1, num2): # 5700 time units (accurate)
tmp = f"{num1}{num2}" # 3500 time units
tmp = int(tmp) # 3100 time units
return tmp
那么,我们能看到什么?首先,乘法和加法本质上比连接和转换要快。这应该不足为奇。
有趣的是,虽然计算 digits 的成本与输入的大小无关,并且随着输入的增加而消失在舍入误差中,但对于较小的输入,此成本成为总成本的重要组成部分。