对于所有指数,我需要删除该地方的数字。 整数a,将其转换为String,即S. 在遍历字符串长度后,
for i in range(len(S)):
new =S[:i]+S[i+1:]
有没有更有效的方法从整数中删除数字?
答案 0 :(得分:2)
更新:这似乎违反直觉,但基于字符串的解决方案快得多然后基于int。这里是我的代码和结果,在几秒钟内可以获得103位,226位和472位数字。我决定不在笔记本电脑上测试102139位数字:)
import timeit, math
digits = [100, 200, 500, 1_000, 2_000, 5_000, 10_000, 50_000, 100_000]
def print_str(n):
s = str(n)
for i in range(len(s)):
#print(i)
n2 = int(s[:i] + s[i+1:])
def print_int(a):
p = 1
while p <= a:
n2 = a//p//10*p + a%p
p *= 10
if __name__ == '__main__':
number = 1
for i in digits:
n = 17**math.ceil(math.log(10**i, 17))
str_ = timeit.timeit('print_str(n)', setup='from __main__ import print_str, n', number=number)
int_ = timeit.timeit('print_int(n)', setup='from __main__ import print_int, n', number=number)
print("{:8d}\t{:15.6f}\t{:15.6f}".format(len(str(n)), str_/number*1000, int_/number*1000))
结果(特定数字长度的毫秒数):
$ time python3 main.py
101 0.169280 0.185082
201 0.502591 0.537000
501 3.917680 3.195815
1001 13.768999 22.781801
2001 114.404890 120.546628
5001 1066.541904 1625.172070
10002 8033.144731 8802.031382
50001 937385.167088 1045865.986814
100002 7800950.456252 8189620.010314
第一列 - 基于str的解决方案的位数 - 第二位 - 以毫秒为单位,第三位 - 基于int的位数。
但怎么可能?
可以理解,如果我们记住在Python中如何构造无穷大的整数。在引擎盖下,连接的15位或30位整数数组产生结果数。因此,当你划分这个数字时,你必须遍历整个数组并修改每一个数字。同时考虑到复杂性 - 有时你必须在更重要的数字上加或减,这会使过程变得复杂。
使用字符串时,只能将字节从一个地方复制到另一个地方。它是使用内部cpu指令进行的极快程序。
但是如果我们不需要转换为int呢?例如,我们想要打印一个数字,所以以字符串形式使用它会更好吗?它将如何进入过程?
此处&#39;结果 - 也以毫秒为单位显示
$ time python3 main.py
101 0.051510 0.124668
201 0.091741 0.442547
501 0.357862 2.562110
1001 0.787016 15.229156
2001 2.545076 111.917518
5001 4.993472 1334.944235
UPD:更新版本的Bencharks:
$ time python3 main2.py
digits str1 str2 int1 int2
101 0.047 0.101 0.110 0.073
201 0.091 0.315 0.380 0.145
501 0.338 2.049 2.540 0.778
1001 1.342 16.878 16.032 1.621
2001 1.626 85.277 97.809 5.553
5001 4.903 1039.889 1326.481 32.490
10002 15.987 7856.753 9512.209 129.280
20001 72.205 60363.860 68219.334 487.088
real 2m29.403s
user 2m27.902s
sys 0m0.577s
答案 1 :(得分:1)
你也可以不用字符串来做:
>>> a = 12345
>>> p = 1
>>> while p <= a:
print a/p/10*p + a%p
p *= 10
1234
1235
1245
1345
2345
答案 2 :(得分:1)
另一个产生整数的答案,比我的其他答案和OP的字符串解决方案要快得多:
>>> a = 12345
>>> digits = [0] + list(map(int, str(a)))
>>> p = 10**(len(digits) - 2)
>>> for x, y in zip(digits, digits[1:]):
a += (x - y) * p
p //= 10
print(a)
2345
1345
1245
1235
1234
这是从2345到1345,将2替换为1,它通过减去2⋅1000并加1⋅1000来实现。或者简而言之,通过添加(1-2)⋅1000。然后通过添加(2-3)⋅100从1345到1245。等等。
基准测试结果,使用Eugene程序的修改版本:
digits str1 str2 int1 int2
101 0.085 0.255 0.376 0.157
201 0.161 0.943 1.569 0.389
501 0.514 9.180 9.932 0.983
1001 0.699 30.544 39.796 2.218
2001 1.402 203.429 291.006 8.435
5001 4.852 2691.292 3983.420 50.616
10002 16.080 21139.318 29114.274 197.343
20001 54.884 167641.593 222848.841 789.182
str1是OP的字符串解决方案的时间,产生字符串。
str2是OP的字符串解决方案的时间,将字符串转换为整数 int1是我生成int的另一种解决方案 int2是我生成int的新解决方案。
OP的字符串解决方案总体上是最快的,这并不奇怪。它的运行时复杂度是数字的二次方。这是总输出大小,因此是最佳的。我的新解决方案也是二次方的,但进行计算当然比纯粹复制更有效。
为了生产整体,我的新解决方案是迄今为止最快的。我的旧版本和OP的版本具有立方体运行时间(OP显然是旧版本的1.4倍)。
基准程序(Eugene&#39;的修改版):
import timeit, math
digits = [100, 200, 500, 1_000, 2_000, 5_000, 10_000, 20_000]
def print_str_1(n):
s = str(n)
for i in range(len(s)):
#print(i)
n2 = s[:i] + s[i+1:]
def print_str_2(n):
s = str(n)
for i in range(len(s)):
#print(i)
n2 = int(s[:i] + s[i+1:])
def print_int_1(a):
p = 1
while p <= a:
n2 = a//p//10*p + a%p
p *= 10
def print_int_2(a):
digits = [0] + list(map(int, str(a)))
p = 10**(len(digits) - 2)
for x, y in zip(digits, digits[1:]):
a += (x - y) * p
p //= 10
#print(a)
if __name__ == '__main__':
print(("{:>6}" + 4 * "{:>12}").format('digits', 'str1', 'str2', 'int1', 'int2'))
number = 1
for i in digits:
n = 17**math.ceil(math.log(10**i, 17))
str1 = timeit.timeit('print_str_1(n)', setup='from __main__ import print_str_1, n', number=number)
str2 = timeit.timeit('print_str_2(n)', setup='from __main__ import print_str_2, n', number=number)
int1 = timeit.timeit('print_int_1(n)', setup='from __main__ import print_int_1, n', number=number)
int2 = timeit.timeit('print_int_2(n)', setup='from __main__ import print_int_2, n', number=number)
print(("{:6d}" + 4 * "{:12.3f}").format(len(str(n)), *(x/number*1000 for x in (str1, str2, int1, int2))))