繁体   English   中英

从python中的数字(整数)中删除一个数字

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM