Python中整数的长度

Str*_*des 204 python integer count

在Python中,如何找到整数中的位数?

Gee*_*tra 272

如果你想要一个整数的长度和整数中的位数一样,你总是可以将它转换成字符串,str(133)并找到它的长度len(str(123)).

  • 嘿,这是一个缓慢的解决方案.我做了一个随机6位数的阶乘,并找到了它的长度.这种方法耗时**95.891**秒.并且`Math.log10`方法仅*****7.486343383789062e-05**秒,大约**1501388**倍! (21认同)
  • 当然,如果你正在寻找数字位数,这将产生一个对于负数而言太大的结果,因为它会计算负号. (15认同)
  • 这不仅很慢,而且会消耗更多的内存,并且可能会导致大量问题。使用 `Math.log10` 代替。 (9认同)
  • 但‘0’的位数不就等于1了吗? (7认同)
  • 使用“abs()”删除负号。例如。`len(str(abs(-123))) == 3` (4认同)

Joh*_*ooy 218

没有转换为字符串

import math
digits = int(math.log10(n))+1
Run Code Online (Sandbox Code Playgroud)

还要处理零和负数

import math
if n > 0:
    digits = int(math.log10(n))+1
elif n == 0:
    digits = 1
else:
    digits = int(math.log10(-n))+2 # +1 if you don't count the '-' 
Run Code Online (Sandbox Code Playgroud)

你可能想把它放在一个函数:)

这是一些基准.len(str())即使是非常小的数字,它已经落后了

timeit math.log10(2**8)
1000000 loops, best of 3: 746 ns per loop
timeit len(str(2**8))
1000000 loops, best of 3: 1.1 µs per loop

timeit math.log10(2**100)
1000000 loops, best of 3: 775 ns per loop
 timeit len(str(2**100))
100000 loops, best of 3: 3.2 µs per loop

timeit math.log10(2**10000)
1000000 loops, best of 3: 844 ns per loop
timeit len(str(2**10000))
100 loops, best of 3: 10.3 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • @Glenn:我当然希望你不要暗示这是一个糟糕的解决方案.程序员的天真O(log10 n)解决方案在ad-hoc原型代码中运行良好 - 但我更倾向于在生产代码或公共API中看到数学家优雅的O(1)解决方案.gnibbler为+1. (58认同)
  • 嗨!我有点奇怪,你能解释我为什么`int(math.log10(x))+ 1`为'9999999999999999999999999999999999999999999999999999999999999999999999999`(**71 nines**)返回**72**?我以为我可以依赖log10方法,但我必须使用len(str(x))代替:( (13认同)
  • 我相信我知道奇怪行为的原因,这是由于浮点不准确,例如.`math.log10(999999999999999)`等于`14.999999999999998`所以`int(math.log10(999999999999999))`变为`14`.但是`math.log10(9999999999999999)`等于`16.0`.也许使用`round`是解决这个问题的方法. (6认同)
  • @gnibbler:+1.从未意识到log10可用于查找数字的大小.希望我能再多投票一次:). (5认同)
  • 使用log10是数学家的解决方案; 使用len(str())是程序员的解决方案,更清晰,更简单. (4认同)
  • 通过一些更多的测试:在"10**12"下,"len(str(n))"是最快的.除此之外,普通log10始终是最快的,但高于"10**15",这是不正确的.只有在"10**100"左右,我的解决方案(带有`10**b`检查的~log10)开始击败`len(str(n))`.总之,**使用`len(str(n))`**! (4认同)
  • 我相信它应该是“digits = int(math.floor(math.log10(abs(n))))+1”。这涵盖了 100 加上 2,而实际上它是三位数。对于 1000 也是如此。对于 n=0,则返回 1。负数与正数的位数相同,因此用绝对值进行归一化。边缘情况很重要。 (3认同)
  • 也许“digits = n and 1 + int(math.log(abs(n), 10))” (2认同)
  • @Juliet我喜欢数学,但我不认为log10是一个很好的解决方案.除了已经指出的问题之外,你所声称的时间也不是"O(1)".(类似地,Fibonacci序列的显式数学公式比迭代解决方案的计算速度慢.)对于任何理智的目的,"len(str(n))"足够快,更多Pythonic,而且更不明显. (2认同)
  • 事实上,log10 的执行时间可能比“O(log n)”慢,[根据维基百科](https://en.wikipedia.org/wiki/Computational_complexity_of_mathematical_operations)!尽管如此,因为数学很有趣:为了获得更快的“O(log n)”数学解决方案,首先使用“b = int(n.bit_length() * math.log10(2))”进行近似,然后在必要时通过检查进行舍入如果`n == 0 或abs(n) >= 10**b`。 (2认同)
  • 我的坏:技术上浮点数学大于'O(log n)`,但非常非常快.至于我的近似,结果是`n.bit_length()*math.log10(2)`仅比`math.log10(n)`快得多.但是,我的近似需要对其检查('10**b`)进行取幂,该检查占用大部分时间.`math.log10(n)`需要在`999999999999999`周围进行相同的检查,但是在那个小的值上,`len(str(n))`仍然具有竞争力.¯\ _(ツ)_ /¯ (2认同)

Cal*_*twr 35

所有math.log10解决方案都会给您带来麻烦.

math.log10很快,但是当你的数字大于999999999999997时会出现问题.这是因为浮点数太多.9s,导致结果向上舍入.

解决方案是对高于该阈值的数字使用while计数器方法.

为了使这更快,创建10 ^ 16,10 ^ 17等等,并作为变量存储在列表中.这样,它就像一个表查找.

def getIntegerPlaces(theNumber):
    if theNumber <= 999999999999997:
        return int(math.log10(theNumber)) + 1
    else:
        counter = 15
        while theNumber >= 10**counter:
            counter += 1
        return counter
Run Code Online (Sandbox Code Playgroud)

  • 天哪,这效率太低了。60分怎么样?它甚至比字符串转换慢几个数量级。对于 1040598 位数字 (`2**3456789`),`len(str(number))` 大约需要 12 秒。我在后台忘记了这一点,但它仍然没有完成 (3认同)
  • @Vighnesh Raut:而且幅度更慢 (2认同)

Ale*_*lli 22

Python 2.* int需要4或8个字节(32或64位),具体取决于您的Python构建. sys.maxint(2**31-1对于32位整数,2**63-1对于64位整数)将告诉您获得两种可能性中的哪一种.

在Python 3中,ints(与longPython 2中的s一样)可以采用任意大小的可用内存量; sys.getsizeof为您提供任何给定值一个很好的迹象,但它确实也算一些固定开销:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Run Code Online (Sandbox Code Playgroud)

如果像其他答案所暗示的那样,你正在考虑整数值的一些字符串表示,那么只需要使用len该表示,无论是在基数10还是其他方面!

  • 这看起来很有趣,但不确定如何提取长度 (2认同)

BiG*_*YaN 15

设数是n那么数字的位数n由下式给出:

math.floor(math.log10(n))+1
Run Code Online (Sandbox Code Playgroud)

请注意,这将为+ ve整数<10e15提供正确的答案.除此之外,返回类型的精确限制math.log10和答案可能会被1关闭.我只会len(str(n))超越它; 这需要O(log(n))时间与迭代10次幂相同.

感谢@SetiVolkylany将我的注意力带到了这个限制.令人惊讶的是,看似正确的解决方案在实现细节方面有一些警告.

  • 尝试使用Python2.7或Python3.5```&gt;&gt;&gt;&gt; math.floor(math.log10(999999999999997))+ 1 15.0 &gt;&gt;&gt; math.floor(math.log10(999999999999998))+ 1 16.0` ``。看我的回答http://stackoverflow.com/a/42736085/6003870。 (2认同)

odr*_*dek 12

好吧,如果没有转换为字符串,我会做类似的事情:

def lenDigits(x): 
    """
    Assumes int(x)
    """

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)
Run Code Online (Sandbox Code Playgroud)

极简主义递归FTW

  • 您将达到大数的递归限制。 (2认同)

dat*_*new 12

计算没有将整数转换为字符串的位数:

x=123
x=abs(x)
i = 0
while x >= 10**i:
    i +=1
# i is the number of digits
Run Code Online (Sandbox Code Playgroud)


NoO*_*ere 10

自问这个问题以来已经有好几年了,但是我已经为几种计算整数长度的方法编制了基准。

def libc_size(i): 
    return libc.snprintf(buf, 100, c_char_p(b'%i'), i) # equivalent to `return snprintf(buf, 100, "%i", i);`

def str_size(i):
    return len(str(i)) # Length of `i` as a string

def math_size(i):
    return 1 + math.floor(math.log10(i)) # 1 + floor of log10 of i

def exp_size(i):
    return int("{:.5e}".format(i).split("e")[1]) + 1 # e.g. `1e10` -> `10` + 1 -> 11

def mod_size(i):
    return len("%i" % i) # Uses string modulo instead of str(i)

def fmt_size(i):
    return len("{0}".format(i)) # Same as above but str.format
Run Code Online (Sandbox Code Playgroud)

(libc函数需要一些设置,我没有包括在内)

size_exp感谢Brian Preslopsky,size_str感谢GeekTantra和size_mathJohn La Rooy

结果如下:

Time for libc size:      1.2204 ?s
Time for string size:    309.41 ns
Time for math size:      329.54 ns
Time for exp size:       1.4902 ?s
Time for mod size:       249.36 ns
Time for fmt size:       336.63 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.240835x)
+ math_size (1.321577x)
+ fmt_size (1.350007x)
+ libc_size (4.894290x)
+ exp_size (5.976219x)
Run Code Online (Sandbox Code Playgroud)

(免责声明:该函数在输入1到1,000,000上运行)

下面是结果sys.maxsize - 100000sys.maxsize

Time for libc size:      1.4686 ?s
Time for string size:    395.76 ns
Time for math size:      485.94 ns
Time for exp size:       1.6826 ?s
Time for mod size:       364.25 ns
Time for fmt size:       453.06 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.086498x)
+ fmt_size (1.243817x)
+ math_size (1.334066x)
+ libc_size (4.031780x)
+ exp_size (4.619188x)
Run Code Online (Sandbox Code Playgroud)

如您所见,mod_sizelen("%i" % i))是最快的,比使用速度稍快,str(i)并且比其他速度快得多。


PAD*_*MKO 7

如亲爱的用户@Calvintwr所述,该函数math.log10在范围[-999999999999997,999999999999997]之外的数字中存在问题,我们得到浮点错误.我在使用JavaScript(Google V8和NodeJS)和C(GNU GCC编译器)时遇到了这个问题,因此'purely mathematically'这里不可能找到解决方案.


基于这个要点和亲爱的用户@Calvintwr 的答案

import math


def get_count_digits(number: int):
    """Return number of digits in a number."""

    if number == 0:
        return 1

    number = abs(number)

    if number <= 999999999999997:
        return math.floor(math.log10(number)) + 1

    count = 0
    while number:
        count += 1
        number //= 10
    return count
Run Code Online (Sandbox Code Playgroud)

我测试了长度高达20(含)的数字并且可以.它必须足够,因为64位系统上的长度最大整数是19(len(str(sys.maxsize)) == 19).

assert get_count_digits(-99999999999999999999) == 20
assert get_count_digits(-10000000000000000000) == 20
assert get_count_digits(-9999999999999999999) == 19
assert get_count_digits(-1000000000000000000) == 19
assert get_count_digits(-999999999999999999) == 18
assert get_count_digits(-100000000000000000) == 18
assert get_count_digits(-99999999999999999) == 17
assert get_count_digits(-10000000000000000) == 17
assert get_count_digits(-9999999999999999) == 16
assert get_count_digits(-1000000000000000) == 16
assert get_count_digits(-999999999999999) == 15
assert get_count_digits(-100000000000000) == 15
assert get_count_digits(-99999999999999) == 14
assert get_count_digits(-10000000000000) == 14
assert get_count_digits(-9999999999999) == 13
assert get_count_digits(-1000000000000) == 13
assert get_count_digits(-999999999999) == 12
assert get_count_digits(-100000000000) == 12
assert get_count_digits(-99999999999) == 11
assert get_count_digits(-10000000000) == 11
assert get_count_digits(-9999999999) == 10
assert get_count_digits(-1000000000) == 10
assert get_count_digits(-999999999) == 9
assert get_count_digits(-100000000) == 9
assert get_count_digits(-99999999) == 8
assert get_count_digits(-10000000) == 8
assert get_count_digits(-9999999) == 7
assert get_count_digits(-1000000) == 7
assert get_count_digits(-999999) == 6
assert get_count_digits(-100000) == 6
assert get_count_digits(-99999) == 5
assert get_count_digits(-10000) == 5
assert get_count_digits(-9999) == 4
assert get_count_digits(-1000) == 4
assert get_count_digits(-999) == 3
assert get_count_digits(-100) == 3
assert get_count_digits(-99) == 2
assert get_count_digits(-10) == 2
assert get_count_digits(-9) == 1
assert get_count_digits(-1) == 1
assert get_count_digits(0) == 1
assert get_count_digits(1) == 1
assert get_count_digits(9) == 1
assert get_count_digits(10) == 2
assert get_count_digits(99) == 2
assert get_count_digits(100) == 3
assert get_count_digits(999) == 3
assert get_count_digits(1000) == 4
assert get_count_digits(9999) == 4
assert get_count_digits(10000) == 5
assert get_count_digits(99999) == 5
assert get_count_digits(100000) == 6
assert get_count_digits(999999) == 6
assert get_count_digits(1000000) == 7
assert get_count_digits(9999999) == 7
assert get_count_digits(10000000) == 8
assert get_count_digits(99999999) == 8
assert get_count_digits(100000000) == 9
assert get_count_digits(999999999) == 9
assert get_count_digits(1000000000) == 10
assert get_count_digits(9999999999) == 10
assert get_count_digits(10000000000) == 11
assert get_count_digits(99999999999) == 11
assert get_count_digits(100000000000) == 12
assert get_count_digits(999999999999) == 12
assert get_count_digits(1000000000000) == 13
assert get_count_digits(9999999999999) == 13
assert get_count_digits(10000000000000) == 14
assert get_count_digits(99999999999999) == 14
assert get_count_digits(100000000000000) == 15
assert get_count_digits(999999999999999) == 15
assert get_count_digits(1000000000000000) == 16
assert get_count_digits(9999999999999999) == 16
assert get_count_digits(10000000000000000) == 17
assert get_count_digits(99999999999999999) == 17
assert get_count_digits(100000000000000000) == 18
assert get_count_digits(999999999999999999) == 18
assert get_count_digits(1000000000000000000) == 19
assert get_count_digits(9999999999999999999) == 19
assert get_count_digits(10000000000000000000) == 20
assert get_count_digits(99999999999999999999) == 20
Run Code Online (Sandbox Code Playgroud)

使用Python 3.5测试的所有代码示例


小智 5

这是一个庞大但快速的版本:

def nbdigit ( x ):
    if x >= 10000000000000000 : # 17 -
        return len( str( x ))
    if x < 100000000 : # 1 - 8
        if x < 10000 : # 1 - 4
            if x < 100             : return (x >= 10)+1 
            else                   : return (x >= 1000)+3
        else: # 5 - 8                                                 
            if x < 1000000         : return (x >= 100000)+5 
            else                   : return (x >= 10000000)+7
    else: # 9 - 16 
        if x < 1000000000000 : # 9 - 12
            if x < 10000000000     : return (x >= 1000000000)+9 
            else                   : return (x >= 100000000000)+11
        else: # 13 - 16
            if x < 100000000000000 : return (x >= 10000000000000)+13 
            else                   : return (x >= 1000000000000000)+15
Run Code Online (Sandbox Code Playgroud)

对于不太大的数字,仅进行 5 次比较。在我的电脑上,它比版本快大约 30% math.log10,比len( str())原来快 5%。好吧……如果你不疯狂地使用它的话,不会那么有吸引力。

这是我用来测试/测量我的功能的一组数字:

n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
Run Code Online (Sandbox Code Playgroud)

注意:它不管理负数,但适应很容易......