Python中整数的长度


232

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


1
我不明白你的问题。你是说整数的大小吗?您要查找数字位数吗?请澄清。
batbrat'2

Answers:


317

如果您希望整数的长度与整数的位数一样,则可以始终将其转换为string,str(133)并找到其长度,如len(str(123))


18
当然,如果您要查找数字位数,这将产生对于负数太大的结果,因为它将计算负数。
克里斯·厄普彻奇

37
嘿,这是一个缓慢的解决方案。我做了一个随机的6位数的阶乘,发现了它的长度。此方法花费了95.891秒。而且Math.log10方法 花费7.486343383789062e-05秒,大约快了1501388倍!
FadedCoder

1
这不仅很慢,而且会消耗更多的内存,并且可能导致大量麻烦。使用Math.log10代替。
Peyman

245

不转换为字符串

import math
digits = int(math.log10(n))+1

同时处理零和负数

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 '-' 

您可能希望将其放入函数中:)

这是一些基准。在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

5
为此使用log10是数学家的解决方案。使用len(str())是程序员的解决方案,并且更清晰,更简单。
Glenn Maynard'2

68
@Glenn:我当然希望您不要暗示这是一个不好的解决方案。程序员的幼稚O(log10 n)解决方案在即席即用的原型代码中很好地工作了-但我更希望数学家在生产代码或公共API中看到优雅的O(1)解决方案。+1咬人。
朱丽叶

5
@gnibbler:+1。从来没有意识到log10可用于查找数字的大小。希望我能再投票一次:)。
阿巴斯

14
嗨!我去一些奇怪的事情,你的任何人都可以请解释一下我为什么int(math.log10(x)) +19999999999999999999999999999999999999999999999999999999999999999999999971九)返回72?我以为我可以依靠log10方法,但是我必须改用len(str(x)):(
Marecky 2012年

6
我相信我知道这种奇怪行为的原因,这是由于浮点数不准确所致。math.log10(999999999999999)等于14.999999999999998所以int(math.log10(999999999999999))变得14。但是math.log10(9999999999999999)等于16.0。也许使用round是解决此问题的方法。
jamylak'4

43

所有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

谢谢。这是一个很好的反例math.log10。有趣的是,看到二进制表示形式如何翻转给出数学错误结果的值。
WloHu

则len(str(num))会更好
Vighnesh Raut

2
@Vighnesh Raut:幅度更慢
Chaitanya Bangera

“依靠浮点运算给出准确的结果是危险的” -Mark
Sreeragh AR,

26

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

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

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

如果,正如其他答案所暗示的那样,如果您正在考虑某个整数值的字符串表示形式,则只需采用该len表示形式的形式即可,无论是以10还是10为底!


抱歉,此答案已被删除。它提供了信息,而且很有意义(如果只是更具体地确定需要哪个“ len”)。+1
mjv'2

这看起来很有趣,但不确定如何提取长度
Tjorriemorrie

17

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

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

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

size_exp感谢Brian Preslopsky,size_str感谢GeekTantra,以及size_math John 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)

(免责声明:该函数在输入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)

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


您确实应该包括libc安装程序libc = ctyle.CDLL('libc.so.6', use_errno=True)(猜测就是这样)。它不适用于大于数字的情况,sys.maxsize因为浮点数不能“很大”。因此,在此之上的任何数字,我想您都只能使用较慢的方法之一。
10/27

15

设数字为,n则数字的位数n为:

math.floor(math.log10(n))+1

请注意,这将为+ ve整数<10e15给出正确的答案。除此之外,返回类型的精度限制math.log10和答案可能会相差1 len(str(n))。这需要的O(log(n))时间与对10的幂进行迭代相同。

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


1
它不工作,如果范围n以外[-999999999999997,999999999999997]
PADYMKO

@SetiVolkylany,我测试了它直到python2.7和3.5的50位。只是做一个assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
BiGYAN

2
尝试使用Python2.7或Python3.5 >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0。看我的答案stackoverflow.com/a/42736085/6003870
PADYMKO'Mar 3''13

12

好吧,如果不转换为字符串,我将执行以下操作:

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

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

极简递归FTW


1
您将达到大量的递归限制。
nog642

9

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

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

好的人完全避免了字符串转换。
Patrick Mutuku

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

我测试了长度不超过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

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


3

对于后代来说,毫无疑问,这是迄今为止最慢的解决方案:

def num_digits(num, number_of_calls=1):
    "Returns the number of digits of an integer num."
    if num == 0 or num == -1:
        return 1 if number_of_calls == 1 else 0
    else:
        return 1 + num_digits(num/10, number_of_calls+1)


1

假设您要求存储的最大数字整数,则该值取决于实现。我建议您在使用python时不要以这种方式思考。无论如何,可以在python'integer'中存储很大的值。记住,Python使用鸭子类型!

编辑: 我在澄清询问者要求数字位数之前给出了答案。为此,我同意接受的答案所建议的方法。没有什么可添加的!


1
def length(i):
  return len(str(i))

1

可以使用以下方法快速完成整数操作:

len(str(abs(1234567890)))

它获取绝对值“ 1234567890”的字符串的长度

abs返回没有任何负数的数字(仅数字的大小),str将其转换/转换为字符串,并len返回该字符串的字符串长度。

如果您希望它适用于浮点数,则可以使用以下两种方法之一:

# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])

# Ignore just the decimal place
len(str(abs(0.1234567890)))-1

备查。


我认为这将是简单截断输入数字本身(例如用投地int),而不是截断其十进制字符串表示:len(str(abs(int(0.1234567890))))返回1
大卫·福斯特

不,那是行不通的。如果将0.17转换为整数,则得到0,并且其长度将不同于0.17的长度
Frogboxe

在第一种情况下,通过截断字符串表示形式中的小数点(包括小数点),可以有效地计算数字整数部分的长度,这也是我的建议。0.17这两个解决方案返回1
大卫·福斯特

0

以科学记数法表示格式并得出指数:

int("{:.5e}".format(1000000).split("e")[1]) + 1

我不知道速度,但这很简单。

请注意,小数点后的有效位数(如果将科学计数的小数部分四舍五入到另一个数字,则“ .5e”中的“ 5”可能是一个问题。我将其设置为任意大,但可以反映您知道的最大数字的长度。


0
def count_digit(number):
  if number >= 10:
    count = 2
  else:
    count = 1
  while number//10 > 9:
    count += 1
    number = number//10
  return count

尽管这段代码可以解决问题,但包括解释如何以及为什么解决该问题的说明,确实可以帮助提高您的帖子质量,并可能导致更多的投票。请记住,您将来会为读者回答问题,而不仅仅是现在问的人。请编辑您的答案以添加说明,并指出适用的限制和假设。
阿德里安·摩尔

0

如果必须要求用户输入内容,然后必须计算有多少个数字,则可以按照以下步骤操作:

count_number = input('Please enter a number\t')

print(len(count_number))

注意:切勿将int用作用户输入。


您在此处描述的一个相当具体的情况,因为它实际上与字符串的长度有关。另外,我可以输入任何非数字字符,但您仍然会相信它是一个数字。

0
def digits(n)
    count = 0
    if n == 0:
        return 1
    while (n >= 10**count):
        count += 1
        n += n%10
    return count
print(digits(25))   # Should print 2
print(digits(144))  # Should print 3
print(digits(1000)) # Should print 4
print(digits(0))    # Should print 1

0

我的代码与此相同;我使用了log10方法:

from math import *

def digit_count(数字):

if number>1 and round(log10(number))>=log10(number) and number%10!=0 :
    return round(log10(number))
elif  number>1 and round(log10(number))<log10(number) and number%10!=0:
    return round(log10(number))+1
elif number%10==0 and number!=0:
    return int(log10(number)+1)
elif number==1 or number==0:
    return 1

我必须指定1和0的情况,因为log10(1)= 0和log10(0)= ND,因此不满足提到的条件。但是,此代码仅适用于整数。


0

这是一个笨重但快速的版本:

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

对于不太大的数字,只有5个比较。在我的计算机上,它比该math.log10版本快30%,比该版本快5%len( str())。好吧...如果您不疯狂使用它,那么没有吸引力。

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

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

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


-13
>>> a=12345
>>> a.__str__().__len__()
5

6
不要直接调用特殊方法。那是书面的len(str(a))
Mike Graham 2010年

8
@ ghostdog74仅仅因为有一个电源插座,并不意味着您必须将手指伸入其中。

3
因此,如果您反对这样做,为什么不告诉我使用它有什么问题呢?
ghostdog74'2010-2-3

11
Python内部人员可以使用“魔术” __方法来进行回调,而不是直接调用您的代码。这是好莱坞框架模式:不要打电话给我们,我们会打电话给你。但是,此框架的目的是这些是标准Python内置程序可以使用的魔术方法,以便您的类可以自定义内置程序的行为。如果您的代码可以直接调用该方法,请为该方法指定一个非“ __”的名称。显然,这将那些供程序员使用的方法与从Python内置函数提供给回调的方法区分开来。
PaulMcG 2010年

7
这是一个坏主意,因为已知宇宙中的其他所有人都使用str()和len()。为了与众不同,这是不同的,这本质上是一件坏事-更不用说它只是丑陋的地狱。-1。
Glenn Maynard'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.