如何在整数中找到数字的长度?

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

667151 次浏览

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

假设您要求的是可以存储在整数中的最大数字,则该值与实现有关。我建议你在使用python时不要这样想。在任何情况下,相当大的值都可以存储在python 'integer'中。记住,Python使用鸭子类型!

< em >编辑: 我在澄清提问者想要数字数之前给出了我的答案。就此而言,我同意公认答案所建议的方法。没什么可补充的了!< / p >

不需要转换为字符串

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

也可以处理0和负数

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

Python 2.* ints占用4或8字节(32或64位),这取决于你的Python版本。sys.maxint (2**31-1用于32位整型,2**63-1用于64位整型)将告诉你两种可能性中哪一种获得。

在Python 3中,__abc0(就像Python 2中的__abc1)可以取任意大小,直到可用内存的数量;sys.getsizeof为任何给定值提供了一个很好的指示,尽管也计算了一些固定开销:

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

如果像其他答案所暗示的那样,你正在考虑整数值的字符串表示形式,那么只需取该表示形式的len,无论是以10为基数还是以其他方式!

>>> a=12345
>>> a.__str__().__len__()
5
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1
def length(i):
return len(str(i))

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

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

注意,这将给出+ve整数<的正确答案;10 e15。除此之外,math.log10返回类型的精度限制开始生效,答案可能相差1。我将简单地使用len(str(n));这需要O(log(n))时间,这与10的幂次迭代相同。

感谢@SetiVolkylany让我注意到这个限制。令人惊讶的是,看似正确的解决方案在实现细节中有警告。

对于子孙后代来说,这无疑是迄今为止解决这个问题最慢的方法:

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)

所有的数学。Log10的解会给你带来问题。

数学。Log10速度很快,但当你的数字大于999999999999997时就会出现问题。这是因为浮点数有太多的.9,导致结果四舍五入。

因此,为了获得最佳性能,对于较小的数字使用math.log,并且在math.log可以处理的范围之外只使用len(str()):

def getIntegerPlaces(theNumber):
if theNumber <= 999999999999997:
return int(math.log10(theNumber)) + 1
else:
return len(str(theNumber))

好吧,如果不转换为字符串,我会这样做:

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


x = abs(x)


if x < 10:
return 1


return 1 + lenDigits(x / 10)

最小递归FTW

对于整数,可以使用以下方法快速完成:

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

供以后参考。

正如亲爱的用户@Calvintwr所提到的,函数math.log10在一个超出范围[- 99999999999999997,99999999999999997]的数字中有问题,我们会得到浮点错误。我有这个问题与JavaScript(谷歌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(包括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测试的代码示例

科学记数法格式,去掉指数:

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

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

请注意小数点后的有效数位数(“5”在”。如果5e”将科学记数法的小数部分舍入到另一个数字,则可能会出现问题。我把它设得任意大,但可以反映出你所知道的最大数字的长度。

计算w/o将整数转换为字符串的位数:

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

这个问题已经问了好几年了,但是我已经编写了一个基准测试,其中包含了几种计算整数长度的方法。

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_size (len("%i" % i))是最快的,比使用str(i)略快,比其他方法快得多。

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

如果你必须要求用户输入,然后你必须数出有多少个数字,那么你可以这样做:

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


print(len(count_number))

注意:永远不要使用int作为用户输入。

def digits(n)
count = 0
if n == 0:
return 1
    

if n < 0:
n *= -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

我的代码相同如下,我已经使用了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,因此上面提到的条件不满足。但是,此代码仅适用于整数。

下面是一个体积大但速度快的版本:

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%,比len( str())版本快5%。 好吧……

.

.

下面是我用来测试/测量我的函数的一组数字:

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

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

顶部的答案是说mathlog10更快,但我得到的结果表明len(str(n))更快。

arr = []
for i in range(5000000):
arr.append(random.randint(0,12345678901234567890))
%%timeit


for n in arr:
len(str(n))
//2.72 s ± 304 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit


for n in arr:
int(math.log10(n))+1
//3.13 s ± 545 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

此外,我没有在数学方法中添加逻辑来返回准确的结果,我只能想象这会使它更加缓慢。

我不知道之前的答案是如何证明数学方法更快的。

n = 3566002020360505
count = 0
while(n>0):
count += 1
n = n //10
print(f"The number of digits in the number are: {count}")

output: number中的位数为:16

如果你正在寻找一个不使用内置函数的解决方案。 唯一需要注意的是当你发送a = 000.

def number_length(a: int) -> int:
length = 0
if a == 0:
return length + 1
else:
while a > 0:
a = a // 10
length += 1
return length
    



if __name__ == '__main__':
print(number_length(123)
assert number_length(10) == 2
assert number_length(0) == 1
assert number_length(256) == 3
assert number_length(4444) == 4

这是另一种计算任何数字的小数点前的位数的方法

from math import fabs


len(format(fabs(100),".0f"))
Out[102]: 3


len(format(fabs(1e10),".0f"))
Out[165]: 11


len(format(fabs(1235.4576),".0f"))
Out[166]: 4

我做了一个简短的基准测试,进行了10,000次循环

num     len(str(num))     ----  len(format(fabs(num),".0f")) ---- speed-up
2**1e0  2.179400e-07 sec  ----     8.577000e-07 sec          ---- 0.2541
2**1e1  2.396900e-07 sec  ----     8.668800e-07 sec          ---- 0.2765
2**1e2  9.587700e-07 sec  ----     1.330370e-06 sec          ---- 0.7207
2**1e3  2.321700e-06 sec  ----     1.761305e-05 sec          ---- 0.1318

这是一个较慢但更简单的选择。

但是即使这个解也会给出错误的99999999999998

len(format(fabs(9999999999999998),".0f"))
Out[146]: 16
len(format(fabs(9999999999999999),".0f"))
Out[145]: 17
coin_digit = str(coin_fark).split(".")[1]
coin_digit_len = len(coin_digit)
print(coin_digit_len)

一个快速的解决方案,使用基于"对于整数n和b,有更好的方法计算log(n,b)的下限吗?"的floor(log10(n))的自我纠正实现。

import math


def floor_log(n, b):
res = math.floor(math.log(n, b))
c = b**res
return res + (b*c <= n) - (c > n)


def num_digits(n):
return 1 if n == 0 else 1 + floor_log(abs(n), 10)

这是相当快的,将工作在n < 10**(2**52)(这是非常非常大)。

没有导入和str()这样的函数的解决方案

def numlen(num):
result = 1
divider = 10
while num % divider != num:
divider *= 10
result += 1
return result

这里是最简单的方法,不需要将int转换为字符串:

假设给出的数字为15位,例如;n = 787878899999999;

n=787878899999999
n=abs(n) // we are finding absolute value because if the number is negative int to string conversion will produce wrong output


count=0 //we have taken a counter variable which will increment itself till the last digit


while(n):
n=n//10   /*Here we are removing the last digit of a number...it will remove until 0 digits will left...and we know that while(0) is False*/
count+=1  /*this counter variable simply increase its value by 1 after deleting a digit from the original number
print(count)   /*when the while loop will become False because n=0, we will simply print the value of counter variable

输入:

n=787878899999999

输出:

15

你可以这样用,

n = -123.123
digits = len(str(abs(int(n))))
print(digits)


digitswithdecimals = len(str(abs(n)))-1
print(digitswithdecimals)

输出:

3.

6

解释:

int (n) -从数字中去除任何十进制数

: -123.123 >>-123年

<. . . . . . . . . . . . .#要包含小数点,我们将删除这部分并减去1以排除点'。“比;

abs (int (n)) -从之前的结果中去除负数(如果有的话)

:) -123 >>123

str (abs (int (n))) -将先前的结果转换为字符串

:: 123 >>“123”

len (str (abs (int (n)))) -返回字符串的长度

::: length('123') = 3

您可以使用以下解决方案:

n = input("Enter number: ")
print(len(n))
n = int(n)

正如其他答案所示,使用log10会导致大n的不正确结果,而使用len(str(...))或手动循环会导致大n的性能变慢。Jodag的回答提供了一个非常好的替代方法,它只适用于可能导致计算机崩溃的整数,但我们可以通过完全避免对数而使用二进制来更好地甚至更快(对于n足够小,从而保证math.log2是准确的):

def num_digits(n: int) -> int:
assert n > 0
i = int(0.30102999566398114 * (n.bit_length() - 1)) + 1
return (10 ** i <= n) + i

让我们来分析一下。首先,有一个奇怪的n.bit_length()。这将以二进制形式计算长度:

assert 4 == (0b1111).bit_length()
assert 8 == (0b1011_1000).bit_length()
assert 9 == (0b1_1011_1000).bit_length()

与对数不同,这对于整数来说既快速又精确。事实证明,这恰好导致floor(log2(n)) + 1。为了得到单独的floor(log2(n)),我们减去1,因此得到n.bit_length() - 1

接下来,我们乘以0.30102999566398114。这相当于log10(2)稍微四舍五入。这利用对数规则从floor(log2(n))计算出floor(log10(n))的估计值。

现在,你可能想知道我们在这一点上可能有多差,因为虽然0.30102999566398114 * log2(n) ~ log10(n),但对于floor(0.30102999566398114 * floor(log2(n))) ~ floor(log10(n))不是这样的。回想一下x - 1 < floor(x) <= x,以便我们可以快速计算:

log2(n) - 1 < floor(log2(n)) <= log2(n)


log10(n) - 0.30102999566398114 < 0.30102999566398114 * floor(log2(n)) <= log10(n)


floor(log10(n) - 0.30102999566398114) < floor(0.30102999566398114 * floor(log2(n))) <= floor(log10(n))

请注意,floor(log10(n) - 0.30102999566398114)至少是floor(log10(n)) - 1,这意味着我们与结果的距离最多为1。这是最后的修正,我们检查10 ** i <= n,当结果太小时,会导致额外的1 +,当结果刚刚好时,会导致0 +

类似于Jodag的答案,这种方法实际上失败于非常非常大的n,在10 ** 2 ** 52附近的某个地方,其中i超出了-1。然而,这种大小的整数可能会使您的计算机崩溃,所以这应该足够了。