No Python, como você encontra o número de dígitos em um número inteiro?
No Python, como você encontra o número de dígitos em um número inteiro?
Respostas:
Se você deseja o comprimento de um número inteiro como no número de dígitos do número inteiro, sempre pode convertê-lo em string como str(133)
e encontrar seu comprimento como len(str(123))
.
Math.log10
método levou apenas 7,486343383789062e-05 segundos, aproximadamente 1501388 vezes mais rápido!
Math.log10
vez disso.
Sem conversão para string
import math
digits = int(math.log10(n))+1
Para também lidar com números zero e negativos
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 '-'
Você provavelmente gostaria de colocar isso em uma função :)
Aqui estão alguns benchmarks. A len(str())
já está por trás até mesmo para muito pequenos números
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
int(math.log10(x)) +1
que 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 ) retorna 72 ? Eu pensei que eu poderia contar com método log10, mas eu tenho que usar len (str (x)) em vez :(
math.log10(999999999999999)
é igual a 14.999999999999998
assim int(math.log10(999999999999999))
se torna 14
. Mas então math.log10(9999999999999999)
é igual a 16.0
. Talvez o uso round
seja uma solução para esse problema.
math.log10 é rápido, mas apresenta problemas quando seu número é maior que 999999999999997. Isso ocorre porque o flutuador possui muitos 0,9s, fazendo com que o resultado seja arredondado.
A solução é usar um método contador de tempo para números acima desse limite.
Para tornar isso ainda mais rápido, crie 10 ^ 16, 10 ^ 17 e assim por diante e armazene como variáveis em uma lista. Dessa forma, é como uma pesquisa de tabela.
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
. É interessante ver como a representação binária inverte os valores, resultando matematicamente incorreto.
Os Python 2.*
int
usam 4 ou 8 bytes (32 ou 64 bits), dependendo da sua compilação do Python. sys.maxint
( 2**31-1
para entradas de 32 bits, 2**63-1
para entradas de 64 bits) informará qual das duas possibilidades é obtida.
No Python 3, int
s (como long
s no Python 2) podem levar tamanhos arbitrários até a quantidade de memória disponível; sys.getsizeof
dá-lhe uma boa indicação para qualquer valor dado, embora não também contam alguma sobrecarga fixa:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Se, como outras respostas sugerem, você estiver pensando em alguma representação de string do valor inteiro, basta pegar a len
representação, seja na base 10 ou não!
Faz vários anos desde que essa pergunta foi feita, mas eu compilei uma referência de vários métodos para calcular o comprimento de um número inteiro.
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
(a função libc requer alguma configuração, que eu não incluí)
size_exp
é graças a Brian Preslopsky, size_str
é graças a GeekTantra, e size_math
é graças a John La Rooy
Aqui estão os resultados:
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)
(Isenção de responsabilidade: a função é executada nas entradas 1 a 1.000.000)
Aqui estão os resultados para sys.maxsize - 100000
a sys.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)
Como você pode ver, mod_size
( len("%i" % i)
) é o mais rápido, um pouco mais rápido que o uso str(i)
e significativamente mais rápido que os outros.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(supondo que seja isso). E não funciona para números maiores do que sys.maxsize
porque os números de ponto flutuante não podem ser "muito grandes". Portanto, qualquer número acima disso, acho que você está preso a um dos métodos mais lentos.
Seja o número n
então o número de dígitos n
é dado por:
math.floor(math.log10(n))+1
Observe que isso fornecerá respostas corretas para + ve números inteiros <10e15. Além disso, os limites de precisão do tipo de retorno math.log10
entram em ação e a resposta pode ser reduzida em 1. Eu simplesmente usaria len(str(n))
além disso; isso requer O(log(n))
tempo igual à iteração sobre potências de 10.
Agradeço a @SetiVolkylany por trazer minha atenção a essa limitação. É incrível como as soluções aparentemente corretas têm advertências nos detalhes da implementação.
assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
.
>>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0
. Veja minha resposta stackoverflow.com/a/42736085/6003870 .
Conte o número de dígitos sem o número inteiro convertido em uma sequência:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Como mencionado o querido usuário @Calvintwr, a função math.log10
tem problema em um número fora de um intervalo [-999999999999997, 999999999999997], onde obtemos erros de ponto flutuante. Eu tive esse problema com o JavaScript (o Google V8 e o NodeJS) e o C (o compilador GNU GCC), portanto, uma 'purely mathematically'
solução é impossível aqui.
Com base nesta essência e na resposta, o querido usuário @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
Eu testei em números com comprimento de até 20 (inclusive) e tudo bem. Deve ser suficiente, porque o número inteiro máximo do comprimento em um sistema de 64 bits é 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
Todos os exemplos de códigos testados com o Python 3.5
Para a posteridade, sem dúvida, a solução mais lenta para esse problema:
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)
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1
Supondo que você esteja solicitando o maior número que você pode armazenar em um número inteiro, o valor depende da implementação. Sugiro que você não pense dessa maneira ao usar python. De qualquer forma, um valor bastante grande pode ser armazenado em um python 'número inteiro'. Lembre-se, Python usa digitação de pato!
Edit: Eu dei a minha resposta antes do esclarecimento de que o autor da pergunta queria o número de dígitos. Para isso, concordo com o método sugerido pela resposta aceita. Nada mais a acrescentar!
def length(i):
return len(str(i))
Isso pode ser feito para números inteiros rapidamente usando:
len(str(abs(1234567890)))
Que obtém o comprimento da sequência do valor absoluto de "1234567890"
abs
retorna o número SEM quaisquer negativos (somente a magnitude do número), str
converte / converte em uma sequência e len
retorna o comprimento da sequência.
Se você deseja que ele funcione para carros alegóricos, pode usar um dos seguintes:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Para referência futura.
int
) do que para truncar sua representação de seqüência decimal: len(str(abs(int(0.1234567890))))
retornos 1.
Formate em notação científica e retire o expoente:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Eu não sei sobre velocidade, mas é simples.
Observe o número de dígitos significativos após o decimal (o "5" no ".5e" pode ser um problema se arredondar a parte decimal da notação científica para outro dígito. Defino-o arbitrariamente grande, mas pode refletir a comprimento do maior número que você conhece.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Se você precisar pedir a um usuário para fornecer informações e, em seguida, contar quantos números existem, poderá seguir o seguinte:
count_number = input('Please enter a number\t')
print(len(count_number))
Nota: nunca use int como entrada do usuário.
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
Meu código para o mesmo é o seguinte; eu usei o método log10:
from math import *
def digit_count (number):
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
Eu tive que especificar no caso de 1 e 0 porque log10 (1) = 0 e log10 (0) = ND e, portanto, a condição mencionada não é satisfeita. No entanto, esse código funciona apenas para números inteiros.
Aqui está uma versão volumosa, mas rápida:
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
Apenas 5 comparações para números não muito grandes. No meu computador, é cerca de 30% mais rápido que a math.log10
versão e 5% mais rápido que a versão len( str())
. Ok ... não é tão atraente se você não usá-lo furiosamente.
E aqui está o conjunto de números que eu usei para testar / medir minha função:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
NB: não gerencia números negativos, mas a adaptação é fácil ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.