No entiendo tu pregunta. ¿Quiso decir el tamaño de un número entero? ¿Quieres encontrar el número de dígitos? Por favor aclarar
Batbrat
Respuestas:
317
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)).
Por supuesto, si está buscando el número de dígitos, esto producirá un resultado que es demasiado grande para los números negativos, ya que contará el signo negativo.
Chris Upchurch
37
Oye, esta es una solución lenta. Hice un factorial de un número aleatorio de 6 dígitos y encontré su longitud. Este método tardó 95.891 segundos. ¡Y el Math.log10método tomó solo 7.486343383789062e-05 segundos, aproximadamente 1501388 veces más rápido!
FadedCoder
1
Esto no solo es lento, sino que consume mucha más memoria y puede causar problemas en grandes cantidades. utilizar Math.log10en su lugar.
Peyman
246
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))+1elif n ==0:
digits =1else:
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
Usar log10 para esto es la solución de un matemático; El uso de len (str ()) es la solución de un programador, y es más claro y simple.
Glenn Maynard
68
@Glenn: Ciertamente espero que no estés implicando que esta es una mala solución. La ingenua solución O (log10 n) del programador funciona bien en código de creación de prototipos ad-hoc, pero preferiría ver la elegante solución O (1) de matemáticos en código de producción o API pública. +1 para gnibbler.
Julieta
55
@gnibbler: +1. Nunca me di cuenta de que log10 se puede usar para encontrar la magnitud de un número. Ojalá pudiera votar más de una vez :).
Abbas
14
¡Hola! Voy algo extraño, ¿alguien de ustedes puede explicarme por qué int(math.log10(x)) +1para 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 :(
Marecky
66
Creo que sé la razón del extraño comportamiento, se debe a imprecisiones de coma flotante, por ejemplo. math.log10(999999999999999)es igual a 14.999999999999998lo que se int(math.log10(999999999999999))hace 14. Pero entonces math.log10(9999999999999999)es igual a 16.0. Quizás usar roundes una solución a este problema.
jamylak
43
Todas las soluciones de math.log10 te darán problemas.
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.
Gracias. Ese es un buen contraejemplo para math.log10. Es interesante ver cómo la representación binaria voltea los valores dando resultados matemáticamente incorrectos.
WloHu
entonces len (str (num)) sería mejor
Vighnesh Raut
2
@Vighnesh Raut: Y las magnitudes son más lentas
Chaitanya Bangera
"Es peligroso confiar en operaciones de punto flotante que dan resultados exactos" - Mark Dickinson, miembro del equipo central de desarrollo de Python bugs.python.org/issue3724
Sreeragh AR
26
Python 2.*inttoma 4 u 8 bytes (32 o 64 bits), dependiendo de su construcción Python. sys.maxint( 2**31-1para entradas de 32 bits, 2**63-1para entradas de 64 bits) le indicará cuál de las dos posibilidades obtiene.
En Python 3, ints (como longs en Python 2) puede tomar tamaños arbitrarios hasta la cantidad de memoria disponible; sys.getsizeofle da una indicación bueno para cualquier valor dado, a pesar de que no cuentan también algo de sobrecarga fija:
Si, como sugieren otras respuestas, está pensando en alguna representación de cadena del valor entero, simplemente tome lenesa representación, ya sea en la base 10 o de lo contrario.
Lo siento, esta respuesta tiene menos ed. Es informativo y hasta el punto plausible de la pregunta (si fuera más específico sobre qué 'len' se desea). +1
mjv
Esto parece interesante pero no está seguro de cómo extraer la longitud
Tjorriemorrie
17
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 stringdef math_size(i):return1+ math.floor(math.log10(i))# 1 + floor of log10 of idef exp_size(i):return int("{:.5e}".format(i).split("e")[1])+1# e.g. `1e10` -> `10` + 1 -> 11def 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_expes gracias a Brian Preslopsky, size_stres gracias a GeekTantra, y size_mathes gracias a John La Rooy
Aquí están los resultados:
Timefor libc size:1.2204μs
Timefor string size:309.41 ns
Timefor math size:329.54 ns
Timefor exp size:1.4902μs
Timefor mod size:249.36 ns
Timefor 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 - 100000a sys.maxsize:
Timefor libc size:1.4686μs
Timefor string size:395.76 ns
Timefor math size:485.94 ns
Timefor exp size:1.6826μs
Timefor mod size:364.25 ns
Timefor 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.
Realmente deberías incluir la configuración de libc, libc = ctyle.CDLL('libc.so.6', use_errno=True)(supongo que esto es todo). Y no funciona para números mayores que sys.maxsizeporque 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.
Torxed
15
Sea el número, nentonces el número de dígitos nestá 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.log10patadas 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.
No funciona si n está fuera del rango [-999999999999997, 999999999999997]
PADYMKO
@SetiVolkylany, lo probé hasta 50 dígitos para python2.7 y 3.5. Solo haz un assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))].
BiGYaN
2
pruébelo con Python2.7 o Python3.5 >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0. Mira mi respuesta stackoverflow.com/a/42736085/6003870 .
PADYMKO
12
Bueno, sin convertirme en cadena, haría algo como:
def lenDigits(x):"""
Assumes int(x)
"""
x = abs(x)if x <10:return1return1+ lenDigits(x /10)
Nice one evita la conversión de cadenas por completo.
Patrick Mutuku
8
Como mencionó el querido usuario @Calvintwr, la función math.log10tiene 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:return1
number = abs(number)if number <=999999999999997:return math.floor(math.log10(number))+1
count =0while number:
count +=1
number //=10return 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).
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 ==0or num ==-1:return1if number_of_calls ==1else0else:return1+ num_digits(num/10, number_of_calls+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!
Que obtiene la longitud de la cadena del valor absoluto de "1234567890"
absdevuelve el número SIN negativos (solo la magnitud del número), lo strconvierte / convierte en una cadena y lendevuelve 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
Creo que sería más simple truncar el número de entrada en sí (p. Ej., Con una conversión a int) que truncar su representación de cadena decimal: len(str(abs(int(0.1234567890))))devuelve 1.
David Foerster
No, eso no funcionaría. Si convierte 0.17 en un número entero, obtiene 0 y su longitud sería diferente a la longitud de 0.17
Frogboxe
En el primer caso, al truncar todo e incluir el punto decimal de la representación de cadena, está calculando efectivamente la longitud de la parte integral del número, que es lo que hace mi sugerencia también. Para 0.17 ambas soluciones devuelven 1.
David Foerster
0
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.
Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación, y probablemente resultaría en más votos positivos. Recuerde que está respondiendo la pregunta para los lectores en el futuro, no solo la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Adrian Mole
0
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))
Aquí se describe un caso bastante específico, ya que en realidad está relacionado con la longitud de una cadena. Además, podría ingresar cualquier carácter no numérico y aún creería que es un número.
Ben
0
def digits(n)
count =0if n ==0:return1while(n >=10**count):
count +=1
n += n%10return count
print(digits(25))# Should print 2print(digits(144))# Should print 3print(digits(1000))# Should print 4print(digits(0))# Should print 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.
def nbdigit ( x ):if x >=10000000000000000:# 17 -return len( str( x ))if x <100000000:# 1 - 8if x <10000:# 1 - 4if x <100:return(x >=10)+1else:return(x >=1000)+3else:# 5 - 8 if x <1000000:return(x >=100000)+5else:return(x >=10000000)+7else:# 9 - 16 if x <1000000000000:# 9 - 12if x <10000000000:return(x >=1000000000)+9else:return(x >=100000000000)+11else:# 13 - 16if x <100000000000000:return(x >=10000000000000)+13else: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.log10versió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 ...
No llame directamente a métodos especiales. Eso esta escrito len(str(a)).
Mike Graham
8
@ ghostdog74 El hecho de que haya una toma de corriente no significa que tenga que meter los dedos en ella.
3
así que si estás tan en contra, ¿por qué no me dices qué hay de malo en usarlo?
ghostdog74
11
Los métodos "mágicos" están allí para que los internos de Python vuelvan a llamar, no para que su código llame directamente. Es el patrón de Hollywood Framework: no nos llames, te llamaremos. Pero la intención de este marco es que estos son métodos mágicos para que los incorporados en Python estándar utilicen, de modo que su clase pueda personalizar el comportamiento del incorporado. Si es un método para que su código llame directamente, asigne al método un nombre que no sea "__". Esto separa claramente los métodos que están destinados al consumo del programador, en comparación con los que se proporcionan para la devolución de llamada de Python incorporado.
PaulMcG
77
Es una mala idea porque todos los demás en el universo conocido usan str () y len (). Esto es ser diferente en aras de ser diferente, lo cual es inherentemente algo malo, sin mencionar que es feo como el infierno. -1.
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 comolen(str(123))
.fuente
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
Para manejar también números cero y negativos
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ñosfuente
int(math.log10(x)) +1
para99999999999999999999999999999999999999999999999999999999999999999999999
( 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 a14.999999999999998
lo que seint(math.log10(999999999999999))
hace14
. Pero entoncesmath.log10(9999999999999999)
es igual a16.0
. Quizás usarround
es una solución a este problema.Todas las soluciones de math.log10 te darán problemas.
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.
fuente
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 (comolong
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: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.fuente
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.
(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, ysize_math
es gracias a John La RooyAquí están los resultados:
(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
asys.maxsize
:Como puede ver,
mod_size
(len("%i" % i)
) es el más rápido, un poco más rápido que el usostr(i)
y significativamente más rápido que otros.fuente
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(supongo que esto es todo). Y no funciona para números mayores quesys.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ígitosn
está dado por: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íalen(str(n))
más allá de eso; esto requiereO(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.
fuente
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 .Bueno, sin convertirme en cadena, haría algo como:
Recursividad minimalista FTW
fuente
Cuente el número de dígitos sin convertir enteros en una cadena:
fuente
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
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
).Todos los ejemplos de códigos probados con Python 3.5
fuente
Para la posteridad, sin duda, la solución más lenta a este problema es:
fuente
fuente
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!
fuente
fuente
Se puede hacer para enteros rápidamente usando:
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), lostr
convierte / convierte en una cadena ylen
devuelve la longitud de la cadena de esa cadena.Si desea que funcione para flotadores, puede utilizar cualquiera de los siguientes:
Para futura referencia.
fuente
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:
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.
fuente
fuente
Si tiene que pedirle a un usuario que dé su opinión y luego debe contar cuántos números hay, puede seguir esto:
Nota: Nunca tome un int como entrada del usuario.
fuente
fuente
Mi código para el mismo es el siguiente; he usado el método log10:
def digit_count (número):
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.
fuente
Aquí hay una versión voluminosa pero rápida:
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ónlen( 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:
NB: no maneja números negativos, pero la adaptación es fácil ...
fuente
fuente
len(str(a))
.