如何在python中取一个数字的第n位数

zak*_*usa 22 python int

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

number = 9876543210
i = 4
number[i] # should return 6
Run Code Online (Sandbox Code Playgroud)

我怎么能在python中做那样的事情?我应该先将其更改为字符串,然后将其更改为int以进行计算吗?

Chr*_*ler 42

你可以用整数除法和余数方法来做

def get_digit(number, n):
    return number // 10**n % 10

get_digit(987654321, 0)
# 1

get_digit(987654321, 5)
# 6
Run Code Online (Sandbox Code Playgroud)

//以10的功率确实整数除法的数字移动到那些位置,然后%通过10注得到余数,在这个方案中的编号采用零的索引和数量的右侧开始.

  • @Steven你是对的,这个索引来自数字的右侧而不是左侧.它可以被操纵以另一种方式工作,但这似乎更符合你如何考虑数字中的位置.IE索引0获取1s位置,索引1获取10s位置,依此类推. (3认同)
  • OP从数字的左侧开始使用基于1的索引。 (2认同)
  • 除了史蒂文的评论之外,这个解决方案对于 0 到 1 之间的数字也失败。 (2认同)
  • @indigochild对于“number”或“n”位置中0到1之间的数字来说,它当然不会“失败”。您期望什么行为? (2认同)

Pat*_*ugh 20

首先将数字视为字符串

number = 9876543210
number = str(number)
Run Code Online (Sandbox Code Playgroud)

然后得到第一个数字:

number[0]
Run Code Online (Sandbox Code Playgroud)

第四位数:

number[3]
Run Code Online (Sandbox Code Playgroud)

编辑:

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

int(number[0])
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案有效,但并未优化,因为它使用了更多空间。看到这个:/sf/answers/2775130851/ (2认同)
  • 肯定会使用克里斯更优雅,更有效的解决方案 (2认同)

Nat*_*yle 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
Run Code Online (Sandbox Code Playgroud)
def get_digit(number, n):
    if number - 10**n < 0:
        return False
    return number // 10**n % 10

get_digit(4321, 5)
# False
Run Code Online (Sandbox Code Playgroud)

检查此返回值的布尔状态时必须小心。要允许 0 作为有效返回值,不能只使用if get_digit:. 你必须避免if get_digit is False:表现0出错误的价值观。


Sha*_*ayn 5

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

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

字符串方法给出:

         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}
Run Code Online (Sandbox Code Playgroud)

虽然模块化算术方法给出了:


         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}
Run Code Online (Sandbox Code Playgroud)

运行了 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')
Run Code Online (Sandbox Code Playgroud)