[英]Remove a digit from a number(integer) in python
对于所有索引,我需要删除那个地方的数字。 一个整数a,将其转换为String,即S。然后遍历字符串的长度,
for i in range(len(S)):
new =S[:i]+S[i+1:]
有没有更有效的方法从整数中删除数字?
更新:这似乎违反直觉,但基于字符串的解决方案比基于 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 怎么办? 例如,我们要打印一个数字,那么以字符串形式显示它会更好吗? 它将如何加快进程?
这是结果 - 不同长度也以毫秒为单位
$ 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:更新版本的基准:
$ 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
另一个产生整数的答案,比我的其他答案和 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
这通过将 2 替换为 1 来从 2345 变为 1345,它通过减去 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 是我生产整数的另一个解决方案。
int2 是我生产整数的新解决方案。
毫不奇怪,OP 的字符串解决方案总体上是最快的。 它的运行时复杂度是位数的二次方。 这是总输出大小,所以这是最优的。 我的新解决方案也是二次的,但是做计算当然比纯粹的复制要多。
对于生产整数,我的新解决方案是迄今为止最快的。 我的旧版本和 OP 具有立方运行时间(OP 的速度显然是我的旧版本的 1.4 倍左右)。
基准程序(Eugene 的修改版):
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))))
你也可以不使用字符串:
>>> a = 12345
>>> p = 1
>>> while p <= a:
print a/p/10*p + a%p
p *= 10
1234
1235
1245
1345
2345
#This Method will help you Get first n elements
def GetFirstNNumber(number,n):
lenght=int(math.log10(i))+1 #to know the number of digit in the number take log10
print(i//(10**(lenght-n)))
#This Method will help you Remove first n elements
def RemoveFirstNNumber(number,n):
lenght=int(math.log10(i))+1 #to know the number of digit in the number take log10
print(i%(10**(lenght-n)))
i=25985
n=3
GetFirstNNumber(i,n)
RemoveFirstNNumber(i,n)
输出
259
85
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.