Me gustaría saber cómo puedo encontrar la longitud de un número entero en C.
Por ejemplo:
- 1 => 1
- 25 => 2
- 12512 => 5
- 0 => 1
y así.
¿Cómo puedo hacer esto en C?
marabunta2048
Me gustaría saber cómo puedo encontrar la longitud de un número entero en C.
Por ejemplo:
y así.
¿Cómo puedo hacer esto en C?
jordán lewis
¿Por qué no simplemente tomar el logaritmo en base 10 del valor absoluto del número, redondearlo hacia abajo y agregar uno? Esto funciona para números positivos y negativos que no son 0 y evita tener que usar funciones de conversión de cadenas.
los log10
, abs
y floor
funciones son proporcionadas por math.h
. Por ejemplo:
int nDigits = floor(log10(abs(the_integer))) + 1;
Debe envolver esto en una cláusula que asegure que the_integer != 0
ya que log10(0)
devoluciones -HUGE_VAL
de acuerdo a man 3 log
.
Además, es posible que desee agregar uno al resultado final si la entrada es negativa, si está interesado en la longitud del número, incluido su signo negativo.
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
nótese bien La naturaleza de punto flotante de los cálculos involucrados en este método puede hacer que sea más lento que un enfoque más directo. Vea los comentarios de la respuesta de Kangkan para una discusión sobre la eficiencia.
En realidad, deberías usar piso y agregar 1 en su lugar. Math.Ceil(Math.Log(99)) = 2 pero Math.Ceil(Math.Log(10)) = 1. Math.Floor(Math.Log(99)) + 1 = 2 y Math.Floor(Math. Registro (10)) = 2
– Sani Singh Huttunen
18 de junio de 2010 a las 9:20
La pregunta no es del todo clara sobre la definición de longitud (por lo que posiblemente podría haber pensado en ‘número de dígitos excluyendo los ceros iniciales’), pero esperaría que 0 y -1 devuelvan 1 y 2 como la longitud de su representación de caracteres en lugar de que -2147483648 y 1.
–Pete Kirkham
18 de junio de 2010 a las 9:40
@Pete Gracias por recordarme sobre la limitación del dominio del registro y el caso del número negativo: he editado mi respuesta.
– Jordán Lewis
18 de junio de 2010 a las 9:51
+1 agradable y corto: esta es mi respuesta preferida, incluso si es la más lenta; después de todo, la diferencia de velocidad no es enorme y es muy poco probable que este tipo de código sea un rendimiento. cuello de botella de todos modos.
– Eamon Nerbonné
18 de junio de 2010 a las 13:20
Esto no funciona para 9999999999999999999, un número entero de C que se convertirá a un valor doble mayor y, por lo tanto, producirá un recuento erróneo de dígitos. El OP no especificó int
solo entero.
– chqrlie
23 de noviembre de 2015 a las 23:08
Eamon Nerbonne
Si estás interesado en un rápido y muy simple solución, la siguiente podría ser la más rápida (esto depende de la distribución de probabilidad de los números en cuestión):
int lenHelper(unsigned x) {
if (x >= 1000000000) return 10;
if (x >= 100000000) return 9;
if (x >= 10000000) return 8;
if (x >= 1000000) return 7;
if (x >= 100000) return 6;
if (x >= 10000) return 5;
if (x >= 1000) return 4;
if (x >= 100) return 3;
if (x >= 10) return 2;
return 1;
}
int printLen(int x) {
return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}
Si bien es posible que no gane premios por la solución más ingeniosa, es trivial de entender y también de ejecutar, por lo que es rápido.
En un Q6600 usando MSC, comparé esto con el siguiente bucle:
int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);
Esta solución tarda 0,062 s, la segunda solución más rápida de Pete Kirkham utilizando un enfoque de logaritmo inteligente tarda 0,115 s, casi el doble. Sin embargo, para números alrededor de 10000 e inferiores, el registro inteligente es más rápido.
A expensas de cierta claridad, puede superar de forma más fiable el registro inteligente (al menos, en un Q6600):
int lenHelper(unsigned x) {
// this is either a fun exercise in optimization
// or it's extremely premature optimization.
if(x >= 100000) {
if(x >= 10000000) {
if(x >= 1000000000) return 10;
if(x >= 100000000) return 9;
return 8;
}
if(x >= 1000000) return 7;
return 6;
} else {
if(x >= 1000) {
if(x >= 10000) return 5;
return 4;
} else {
if(x >= 100) return 3;
if(x >= 10) return 2;
return 1;
}
}
}
Esta solución sigue siendo de 0,062 s para números grandes y se degrada a alrededor de 0,09 s para números más pequeños, más rápido en ambos casos que el enfoque de registro inteligente. (gcc crea un código más rápido; 0,052 para esta solución y 0,09 s para el enfoque de registro inteligente).
Me estremezco al pensar cómo se vería la segunda versión escrita completamente con el operador ternario…
– Eamon Nerbonné
18 de junio de 2010 a las 13:22
Si esto se usara para masticar largas listas de números, la cantidad de código de bifurcación causaría estragos en la CPU.s branch prediction and not produce the fastest execution I
tengo miedo.
– Lloyd Crawley
23 de octubre de 2013 a las 8:52
En mi punto de referencia, sigue siendo la solución más rápida: tenga en cuenta que todas las demás soluciones integrales también requieren varias ramas, y la única alternativa real es una conversión de int a doble con un registro de punto flotante (que resulta que tampoco es barato) .
– Eamon Nerbonné
23/10/2013 a las 16:15
@earthdan: esa solución está bien, pero bastante lenta debido a las divisiones. También usa siempre más ramas que la segunda versión de este código, y más en promedio que la primera solución publicada aquí. Además, esa solución es bastante inteligente (en el mal sentido) porque la razón por la que funciona no es del todo obvia. Si desea una solución breve y obvia, use stackoverflow.com/a/3068412/42921; si quieres una solución rápida y obvia, usa esto. No puedo imaginar el caso de uso de stackoverflow.com/a/6655759/2382629 (¡aunque, por supuesto, es un ejercicio intelectual divertido!)
– Eamon Nerbonné
17 de marzo de 2014 a las 12:55
zed_0xff
int get_int_len (int value){
int l=1;
while(value>9){ l++; value/=10; }
return l;
}
y el segundo también funcionará para números negativos:
int get_int_len_with_negative_too (int value){
int l=!value;
while(value){ l++; value/=10; }
return l;
}
Me gusta esto. No hay búferes de caracteres temporales con suposiciones sobre el tamaño.
– Noufal Ibrahim
18 de junio de 2010 a las 9:13
Rápido y elegante, sin embargo, esto no funcionará para números negativos. No sé si eso es una preocupación para el cartel de preguntas.
– Jaime Wong
18 de junio de 2010 a las 9:16
va a. darle una oportunidad. regresará 1
– zed_0xff
19 de junio de 2010 a las 10:10
Tienes razón, de hecho lo hará :-). Sería más claro para mí (y no más lento) distinguir ese caso a través de un retorno si en lugar de una negación.
– Eamon Nerbonné
21 de junio de 2010 a las 7:54
Puedes escribir una función como esta:
unsigned numDigits(const unsigned n) {
if (n < 10) return 1;
return 1 + numDigits(n / 10);
}
Fritz G Mehner
longitud de n:
length = ( i==0 ) ? 1 : (int)log10(n)+1;
Probablemente debería evitar el redondeo a través de la conversión y, en su lugar, optar por un enfoque de redondeo más explícito (también conocido como portátil y consistente).
– Chris Lutz
18 de junio de 2010 a las 9:18
como es casting
¿implementado? ¿Cómo se puede implementar una función como piso? (suponemos un procesador con ieee en hardware, o a través de un coprocesador matemático, o la disponibilidad de la función de software para realizar la misma función normalmente presente en los procesadores con capacidad fp)… al final (int) es portátil y consistente en la mayoría de los casos (me atrevo a decir, todos los casos de los que normalmente nos ocupamos)
– ShinTakezou
18 de junio de 2010 a las 9:48
Como se mencionó en otras publicaciones, esto fallará cuando n = 0
– Jaime Wong
18 de junio de 2010 a las 9:59
@Lutz: ¿qué tipo de portabilidad está comprando al asumir que la conversión de doble a int no está definida? ¿Existe realmente una plataforma relevante donde este sea el caso?
– Eamon Nerbonné
18 de junio de 2010 a las 13:34
@Chris Lutz Si se trata de una implementación C compatible con los estándares, entonces obedece Cuando un valor finito de tipo flotante real se convierte en un tipo entero que no sea _Bool, la parte fraccionaria se descarta (es decir, el valor se trunca hacia cero).
–Pete Kirkham
18 de junio de 2010 a las 17:44
sam hocevar
un correcto snprintf
implementación:
int count = snprintf(NULL, 0, "%i", x);
Probablemente debería evitar el redondeo a través de la conversión y, en su lugar, optar por un enfoque de redondeo más explícito (también conocido como portátil y consistente).
– Chris Lutz
18 de junio de 2010 a las 9:18
como es casting
¿implementado? ¿Cómo se puede implementar una función como piso? (suponemos un procesador con ieee en hardware, o a través de un coprocesador matemático, o la disponibilidad de la función de software para realizar la misma función normalmente presente en los procesadores con capacidad fp)… al final (int) es portátil y consistente en la mayoría de los casos (me atrevo a decir, todos los casos de los que normalmente nos ocupamos)
– ShinTakezou
18 de junio de 2010 a las 9:48
Como se mencionó en otras publicaciones, esto fallará cuando n = 0
– Jaime Wong
18 de junio de 2010 a las 9:59
@Lutz: ¿qué tipo de portabilidad está comprando al asumir que la conversión de doble a int no está definida? ¿Existe realmente una plataforma relevante donde este sea el caso?
– Eamon Nerbonné
18 de junio de 2010 a las 13:34
@Chris Lutz Si se trata de una implementación C compatible con los estándares, entonces obedece Cuando un valor finito de tipo flotante real se convierte en un tipo entero que no sea _Bool, la parte fraccionaria se descarta (es decir, el valor se trunca hacia cero).
–Pete Kirkham
18 de junio de 2010 a las 17:44
IVlad
El número de dígitos de un número entero x
es igual a 1 + log10(x)
. Así que puedes hacer esto:
#include <math.h>
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
printf("x has %d digits\n", 1 + (int)log10(x));
}
O puede ejecutar un ciclo para contar los dígitos usted mismo: haga una división entera por 10 hasta que el número sea 0:
int numDigits = 0;
do
{
++numDigits;
x = x / 10;
} while ( x );
Hay que tener un poco de cuidado para volver 1
si el entero es 0
en la primera solución y es posible que también desee tratar enteros negativos (trabajar con -x
si x < 0
).
Sí, un bonito y sencillo. do
lazo.
– chux – Reincorporar a Monica
23 de noviembre de 2015 a las 23:07
¿Cuál es la definición de “longitud” si el número entero es 0? ¿Negativo?
– kennytm
18 de junio de 2010 a las 9:11
Consulte stackoverflow.com/questions/679602/…. Es casi un duplicado, pero no exacto, ya que es una pregunta de .NET.
– ChrisF
♦
18 de junio de 2010 a las 9:36
la pregunta correcta no es la longitud del entero, sino cuál es el número mínimo de dígitos decimales necesarios para representar ese número (mantenido en un C int). log10 es tu amigo: log10(10000) = 4, +1 el número de dígitos (log10 debe ser truncado)… si el num es negativo, necesitas uno más para el símbolo -, si quieres contarlo, y log10(-num) (ya que el registro de un número negativo es “problemático”.
– ShinTakezou
18 de junio de 2010 a las 9:41
¿Qué tan seguro estás de eso?
log10(10000)
devolverá 4 y no 3.999999…?–Keith Thompson
29 de agosto de 2011 a las 5:58
Mmm. El experimento muestra que
log10(10**n)
da el valor exacto para potencias de 10 de 1 a 2**19, al menos con gcc y glibc. Pero no contaría con él para todas las implementaciones. (**
denota exponenciación; no hay tal operador en C.)–Keith Thompson
29 de agosto de 2011 a las 6:02