【问题标题】:How to take the nth digit of a number in python如何在python中取数字的第n位
【发布时间】:2017-01-31 08:41:02
【问题描述】:

我想从 python 中的 N 位数字中取出第 n 位数字。例如:

number = 9876543210
i = 4
number[i] # should return 6

如何在 python 中做类似的事情?是不是应该先改成string再改成int进行计算?

【问题讨论】:

  • int(str(number)[i-1])。或者,如果您需要处理所有数字:for index, digit in enumerate(str(number), start=1): digit = int(digit)
  • Stack Overflow 不是代码编写或教程服务。请edit您的问题并发布您迄今为止尝试过的内容,包括示例输入、预期输出、实际输出(如果有)以及任何错误或回溯的全文

标签: python int


【解决方案1】:

我很好奇这两种流行方法的相对速度 - 转换为字符串和使用模运算 - 所以我对它们进行了分析,并惊讶地发现它们在性能方面有多接近。

(我的用例略有不同,我想获取数字中的所有数字。)

字符串方法给出:

         10000002 function calls in 1.113 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 10000000    1.113    0.000    1.113    0.000 sandbox.py:1(get_digits_str)
        1    0.000    0.000    0.000    0.000 cProfile.py:133(__exit__)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

虽然模算术方法给出了:


         10000002 function calls in 1.102 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 10000000    1.102    0.000    1.102    0.000 sandbox.py:6(get_digits_mod)
        1    0.000    0.000    0.000    0.000 cProfile.py:133(__exit__)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

运行了 10^7 个测试,最大数字大小小于 10^28。

参考代码:

def get_digits_str(num):
    for n_str in str(num):
        yield int(n_str)


def get_digits_mod(num, radix=10):

    remaining = num
    yield remaining % radix

    while remaining := remaining // radix:
        yield remaining % radix


if __name__ == '__main__':

    import cProfile
    import random

    random_inputs = [random.randrange(0, 10000000000000000000000000000) for _ in range(10000000)]

    with cProfile.Profile() as str_profiler:
        for rand_num in random_inputs:
            get_digits_str(rand_num)

    str_profiler.print_stats(sort='cumtime')

    with cProfile.Profile() as mod_profiler:
        for rand_num in random_inputs:
            get_digits_mod(rand_num)

    mod_profiler.print_stats(sort='cumtime')

【讨论】:

    【解决方案2】:

    这是我对这个问题的看法。

    我已经定义了一个函数'index',它接受数字和输入索引并输出所需索引处的数字。

    枚举方法对字符串进行操作,因此首先将数字转换为字符串。由于 Python 中的索引从 0 开始,但所需的功能要求它从 1 开始,因此在 enumerate 函数中放置了一个 1 来表示计数器的开始。

    def index(number, i):
    
        for p,num in enumerate(str(number),1):
    
            if p == i:
                print(num)
    

    【讨论】:

    • 效率很低,为什么要迭代,什么时候可以做str(number)[index]
    【解决方案3】:

    对于 necro-threading,我感到非常抱歉,但我想提供一个解决方案,而不会将整数转换为字符串。此外,我想使用更多类似计算机的思维方式工作,这就是为什么 Chris Mueller 的回答对我来说不够好。

    那么,废话不多说,

    import math
    
    def count_number(number):
        counter = 0
        counter_number = number
        while counter_number > 0:
            counter_number //= 10
            counter += 1
        return counter
    
    
    def digit_selector(number, selected_digit, total):
        total_counter = total
        calculated_select = total_counter - selected_digit
        number_selected = int(number / math.pow(10, calculated_select))
        while number_selected > 10:
            number_selected -= 10
        return number_selected
    
    
    def main():
        x = 1548731588
        total_digits = count_number(x)
        digit_2 = digit_selector(x, 2, total_digits)
        return print(digit_2)
    
    
    if __name__ == '__main__':
        main()
    

    将打印:

    5
    

    希望其他人可能需要这种特定类型的代码。希望对此也有反馈!

    这应该找到整数中的任何数字。

    缺陷:

    效果很好,但是如果您将其用于长数字,则将花费越来越多的时间。我认为可以查看是否有数千个等,然后从 number_selected 中减去这些,但这可能是另一个时间;)

    用法:

    您需要从 1 到 21 的每一行。然后你可以调用 first count_number 让它计算你的整数。

    x = 1548731588
    total_digits = count_number(x)
    

    然后读取/使用digit_selector函数如下:

    digit_selector('在此处插入你的整数', '你想要哪个数字?(从最左边的数字开始为1)', '一共有多少个数字?')

    如果我们有 1234567890,我们需要选择 4,即从左数第 4 位,所以我们输入“4”。

    由于使用了 total_digits,我们知道有多少位数。所以这很容易。

    希望能解释一切!

    PS:特别感谢 CodeVsColor 提供 count_number 函数。我使用此链接:https://www.codevscolor.com/count-number-digits-number-python 帮助我使 digit_selector 工作。

    【讨论】:

      【解决方案4】:

      你可以用整数除法和余数方法来做到这一点

      def get_digit(number, n):
          return number // 10**n % 10
      
      get_digit(987654321, 0)
      # 1
      
      get_digit(987654321, 5)
      # 6
      

      // 执行整数除以 10 的幂以将数字移动到个位,然后 % 获得除以 10 后的余数。请注意,此方案中的编号使用零索引并开始从数字的右侧。

      【讨论】:

      • OP 使用从数字左侧开始的基于 1 的索引。
      • @Steven 你是对的,这个索引从数字的右侧而不是左侧开始。它可以被操纵以另一种方式工作,但这似乎更符合您对数字中位置的看法。 IE。索引 0 获取 1s 的位置,索引 1 获取 10s 的位置,依此类推。
      • 除了 Steven 的评论,这个解决方案对于 0 到 1 之间的数字也失败了。
      • @indigochild 对于numbern 位置中介于0 和1 之间的数字,它肯定不会“失败”。你期望什么行为?
      【解决方案5】:

      我建议为数字的大小添加一个布尔检查。我正在将高毫秒值转换为日期时间。我有从 2 到 200,000,200 的数字,所以 0 是有效的输出。 @Chris Mueller 的函数即使数字小于 10**n 也会返回 0。

      def get_digit(number, n):
          return number // 10**n % 10
      
      get_digit(4231, 5)
      # 0
      

      def get_digit(number, n):
          if number - 10**n < 0:
              return False
          return number // 10**n % 10
      
      get_digit(4321, 5)
      # False
      

      在检查此返回值的布尔状态时必须小心。要允许 0 作为有效的返回值,您不能只使用 if get_digit:。您必须使用if get_digit is False: 来防止0 表现为假值。

      【讨论】:

      • 一个可以返回 0 (int) 作为有效答案同时返回 False (bool) 的函数是错误的秘诀。如果您确实需要检查,最好使用断言或引发异常。此外,如果数字小于 10**n,则为 0 在数学上没有错,所以我不明白为什么应该这样对待它。
      【解决方案6】:

      好的,首先,使用python中的str()函数将'number'转成字符串

      number = 9876543210 #declaring and assigning
      number = str(number) #converting
      

      然后得到索引,0 = 1, 4 = 3 用索引表示法,用int()把它变回数字

      print(int(number[3])) #printing the int format of the string "number"'s index of 3 or '6'
      

      如果你喜欢它的简短形式

      print(int(str(9876543210)[3])) #condensed code lol, also no more variable 'number'
      

      【讨论】:

        【解决方案7】:

        先把数字当作字符串处理

        number = 9876543210
        number = str(number)
        

        然后得到第一个数字:

        number[0]
        

        第四位:

        number[3]
        

        编辑:

        这会将数字作为字符而不是数字返回。要将其转换回使用:

        int(number[0])
        

        【讨论】:

        • 此解决方案有效,但未优化,因为它使用更多空间。看到这个:stackoverflow.com/a/39644726/375966
        • 肯定会使用 Chris 提供的更优雅、更高效的解决方案
        • 有一个浮动怎么样?像 3.125e-10
        • 速度慢,效率低。只需使用number // 10**n % 10,因为这个答案建议:stackoverflow.com/a/39644726/7339624
        • 这个解决方案比使用整数除法和模数的解决方案解决了更多的“数字的数字”问题。尝试使用两者找到以下数字的前导(最左边)数字:723981 4,212,633 1_000_000 983.5 2.04e7
        猜你喜欢
        • 2015-09-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多