En Python, ¿cómo encuentras el número de dígitos en un entero?
En Python, ¿cómo encuentras el número de dígitos en un entero?
Respuestas:
Si desea la longitud de un número entero como el número de dígitos en el número entero, siempre puede convertirlo en una cadena como str(133)
y encontrar su longitud como len(str(123))
.
Math.log10
método tomó solo 7.486343383789062e-05 segundos, aproximadamente 1501388 veces más rápido!
Math.log10
en su lugar.
Sin conversión a cadena
import math
digits = int(math.log10(n))+1
Para manejar también números cero y 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 '-'
Probablemente quieras poner eso en una función :)
Aquí hay algunos puntos de referencia. El len(str())
ya está atrasado incluso para números bastante pequeños
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
para 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 nueves ) devuelve 72 ? Pensé que podía confiar en el método log10, pero tengo que usar len (str (x)) en su lugar :(
math.log10(999999999999999)
es igual a 14.999999999999998
lo que se int(math.log10(999999999999999))
hace 14
. Pero entonces math.log10(9999999999999999)
es igual a 16.0
. Quizás usar round
es una solución a este problema.
math.log10 es rápido pero da problemas cuando su número es mayor que 999999999999997. Esto se debe a que el flotador tiene demasiados .9s, lo que hace que el resultado se redondee.
La solución es usar un método contador de tiempo para números por encima de ese umbral.
Para hacer esto aún más rápido, cree 10 ^ 16, 10 ^ 17, etc., y almacénelos como variables en una lista. De esa manera, es como una búsqueda en la mesa.
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
. Es interesante ver cómo la representación binaria voltea los valores dando resultados matemáticamente incorrectos.
Python 2.*
int
toma 4 u 8 bytes (32 o 64 bits), dependiendo de su construcción Python. sys.maxint
( 2**31-1
para entradas de 32 bits, 2**63-1
para entradas de 64 bits) le indicará cuál de las dos posibilidades obtiene.
En Python 3, int
s (como long
s en Python 2) puede tomar tamaños arbitrarios hasta la cantidad de memoria disponible; sys.getsizeof
le da una indicación bueno para cualquier valor dado, a pesar de que no cuentan también algo de sobrecarga fija:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Si, como sugieren otras respuestas, está pensando en alguna representación de cadena del valor entero, simplemente tome len
esa representación, ya sea en la base 10 o de lo contrario.
Han pasado varios años desde que se hizo esta pregunta, pero he compilado una referencia de varios métodos para calcular la longitud de un número entero.
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
(la función libc requiere cierta configuración, que no he incluido)
size_exp
es gracias a Brian Preslopsky, size_str
es gracias a GeekTantra, y size_math
es gracias a John La Rooy
Aquí están los 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)
(Descargo de responsabilidad: la función se ejecuta en las entradas 1 a 1,000,000)
Aquí están los resultados de 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 puede ver, mod_size
( len("%i" % i)
) es el más rápido, un poco más rápido que el uso str(i)
y significativamente más rápido que otros.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(supongo que esto es todo). Y no funciona para números mayores que sys.maxsize
porque los números de coma flotante no pueden ser "muy grandes". Entonces, cualquier número por encima de eso, supongo que estás atrapado con uno de los métodos más lentos.
Sea el número, n
entonces el número de dígitos n
está dado por:
math.floor(math.log10(n))+1
Tenga en cuenta que esto dará respuestas correctas para + ve enteros <10e15. Más allá de eso, los límites de precisión del tipo de retorno de math.log10
patadas y la respuesta pueden estar apagados en 1. Simplemente usaría len(str(n))
más allá de eso; esto requiere O(log(n))
tiempo, lo mismo que iterar sobre potencias de 10.
Gracias a @SetiVolkylany por llevar mi atención a esta limitación. Es sorprendente cómo las soluciones aparentemente correctas tienen advertencias en los detalles de implementación.
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
. Mira mi respuesta stackoverflow.com/a/42736085/6003870 .
Cuente el número de dígitos sin convertir enteros en una cadena:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Como mencionó el querido usuario @Calvintwr, la función math.log10
tiene un problema en un número fuera de un rango [-999999999999997, 999999999999997], donde obtenemos errores de coma flotante. Tuve este problema con JavaScript (Google V8 y NodeJS) y C (el compilador GNU GCC), por lo que una 'purely mathematically'
solución es imposible aquí.
Basado en esta esencia y la respuesta, el querido usuario @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
Lo probé en números con una longitud de hasta 20 (inclusive) y todo bien. Debe ser suficiente, porque el número entero máximo de longitud en un sistema de 64 bits es 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 los ejemplos de códigos probados con Python 3.5
Para la posteridad, sin duda, la solución más lenta a este problema es:
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
Suponiendo que está solicitando el mayor número que puede almacenar en un entero, el valor depende de la implementación. Sugiero que no pienses de esa manera cuando uses Python. En cualquier caso, se puede almacenar un valor bastante grande en un 'entero' de Python. ¡Recuerde, Python usa la escritura de pato!
Editar: Di mi respuesta antes de la aclaración de que el autor de la pregunta quería el número de dígitos. Para eso, estoy de acuerdo con el método sugerido por la respuesta aceptada. ¡Nada más que agregar!
def length(i):
return len(str(i))
Se puede hacer para enteros rápidamente usando:
len(str(abs(1234567890)))
Que obtiene la longitud de la cadena del valor absoluto de "1234567890"
abs
devuelve el número SIN negativos (solo la magnitud del número), lo str
convierte / convierte en una cadena y len
devuelve la longitud de la cadena de esa cadena.
Si desea que funcione para flotadores, puede utilizar cualquiera de los siguientes:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Para futura referencia.
int
) que truncar su representación de cadena decimal: len(str(abs(int(0.1234567890))))
devuelve 1.
Formatear en notación científica y extraer el exponente:
int("{:.5e}".format(1000000).split("e")[1]) + 1
No sé acerca de la velocidad, pero es simple.
Tenga en cuenta el número de dígitos significativos después del decimal (el "5" en el ".5e" puede ser un problema si redondea la parte decimal de la notación científica a otro dígito. Lo configuré arbitrariamente grande, pero podría reflejar el longitud del mayor número que conoces.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Si tiene que pedirle a un usuario que dé su opinión y luego debe contar cuántos números hay, puede seguir esto:
count_number = input('Please enter a number\t')
print(len(count_number))
Nota: Nunca tome un int como entrada del usuario.
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
Mi código para el mismo es el siguiente; he usado el método log10:
from math import *
def digit_count (número):
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
Tuve que especificar en el caso de 1 y 0 porque log10 (1) = 0 y log10 (0) = ND y, por lo tanto, la condición mencionada no se cumple. Sin embargo, este código solo funciona para números enteros.
Aquí hay una versión voluminosa pero 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
Solo 5 comparaciones para números no demasiado grandes. En mi computadora es aproximadamente un 30% más rápido que la math.log10
versión y un 5% más rápido que la versión len( str())
. Ok ... no tan atractivo si no lo usas furiosamente.
Y aquí está el conjunto de números que usé para probar / medir mi función:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
NB: no maneja números negativos, pero la adaptación es fácil ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.