tipo - Encontrar la longitud de un entero en C
tipos de variables en lenguaje c (18)
Me gustaría saber cómo puedo encontrar la longitud de un entero en C.
Por ejemplo:
- 1 => 1
- 25 => 2
- 12512 => 5
- 0 => 1
y así.
¿Cómo puedo hacer esto en C?
DO:
¿Por qué no simplemente tomar el registro de base 10 del valor absoluto del número, redondearlo y agregar uno? Esto funciona para números positivos y negativos que no son 0, y evita tener que usar cualquier función de conversión de cadenas.
Las funciones log10
, abs
y floor
son provistas por math.h
Por ejemplo:
int nDigits = floor(log10(abs(the_integer))) + 1;
Debería envolver esto en una cláusula que garantice que the_integer != 0
, ya que log10(0)
devuelve -HUGE_VAL
según man 3 log
.
Además, es posible que desee agregar uno al resultado final si la entrada es negativa, si le interesa la longitud del número, incluido su signo negativo.
Java:
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
NB 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.
Bastante sencillo
int main() {
int num = 123;
char buf[50];
// convert 123 to string [buf]
itoa(num, buf, 10);
// print our string
printf("%s/n", strlen (buf));
return 0;
}
Creo que encontré la forma más eficiente de encontrar la longitud de un entero de una manera muy simple y elegante aquí:
int PEMath::LengthOfNum(int Num)
{
int count = 1; //count starts at one because its the minumum amount of digits posible
if (Num < 0)
{
Num *= (-1);
}
for(int i = 10; i <= Num; i*=10)
{
count++;
}
return count;
// this loop will loop until the number "i" is bigger then "Num"
// if "i" is less then "Num" multiply "i" by 10 and increase count
// when the loop ends the number of count is the length of "Num".
}
En mi opinión, la solución más corta y más fácil sería:
int length , n;
printf("Enter a number: ");
scanf("%d", &n);
length = 0;
while (n > 0) {
n = n / 10;
length++;
}
printf("Length of the number: %d", length);
La cantidad de dígitos de un entero x
es igual a 1 + log10(x)
. Entonces 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 la división de enteros por 10 hasta que el número sea 0:
int numDigits = 0;
do
{
++numDigits;
x = x / 10;
} while ( x );
Debe tener cuidado de devolver 1
si el entero es 0
en la primera solución y también puede tratar números enteros negativos (trabajo con -x
si x < 0
).
La forma más eficiente podría ser utilizar un enfoque basado en el logaritmo rápido, similar a los utilizados para determinar el bit más alto establecido en un número entero.
size_t printed_length ( int32_t x )
{
size_t count = x < 0 ? 2 : 1;
if ( x < 0 ) x = -x;
if ( x >= 100000000 ) {
count += 8;
x /= 100000000;
}
if ( x >= 10000 ) {
count += 4;
x /= 10000;
}
if ( x >= 100 ) {
count += 2;
x /= 100;
}
if ( x >= 10 )
++count;
return count;
}
Esta optimización (posiblemente prematura) requiere 0.65s para 20 millones de llamadas en mi netbook; La división iterativa como zed_0xff tiene 1.6s, división recursiva como Kangkan toma 1.8s, y el uso de funciones de coma flotante (código de Jordan Lewis) toma 6.6s. Usar snprintf toma 11.5s, pero le dará el tamaño que snprintf requiere para cualquier formato, no solo para enteros. Jordan informa que el orden de los tiempos no se mantiene en su procesador, que hace punto flotante más rápido que el mío.
El más fácil es, probablemente, pedir snprintf para la longitud impresa:
#include <stdio.h>
size_t printed_length ( int x )
{
return snprintf ( NULL, 0, "%d", x );
}
int main ()
{
int x[] = { 1, 25, 12512, 0, -15 };
for ( int i = 0; i < sizeof ( x ) / sizeof ( x[0] ); ++i )
printf ( "%d -> %d/n", x[i], printed_length ( x[i] ) );
return 0;
}
Mi manera:
Divida siempre que el número no sea más divisible por 10:
u8 NumberOfDigits(u32 number)
{
u8 i = 1;
while (number /= 10) i++;
return i;
}
No sé qué tan rápido está en comparación con otras proposiciones ...
Puedes escribir una función como esta:
unsigned numDigits(const unsigned n) {
if (n < 10) return 1;
return 1 + numDigits(n / 10);
}
Puedes usar esto -
(data_type) log10 (variable_name) +1
ex:
len = (int) log10 (número) +1;
Sí, usando sprintf.
int num;
scanf("%d",&num);
char testing[100];
sprintf(testing,"%d",num);
int length = strlen(testing);
Alternativamente, puede hacer esto matemáticamente usando la función log10
.
int num;
scanf("%d",&num);
int length;
if (num == 0) {
length = 1;
} else {
length = log10(fabs(num)) + 1;
if (num < 0) length++;
}
Si está interesado en una solución rápida y muy simple , lo siguiente puede ser más rápido (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 trivial de ejecutar, por lo que es rápido.
En un Q6600 usando MSC, lo comparé con el siguiente ciclo:
int res=0;
for(int i=-2000000000;i<2000000000;i+=200) res+=printLen(i);
Esta solución toma 0.062s, la segunda solución más rápida de Pete Kirkham usando un enfoque de logaritmo inteligente toma 0.115s, casi el doble de tiempo. Sin embargo, para números alrededor de 10000 y menos, el registro inteligente es más rápido.
A costa de algo de claridad, puede vencer de manera más fiable al Smart-Log (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 0.062s en números grandes, y se degrada a alrededor de 0.09s para números más pequeños, más rápido en ambos casos que el enfoque de registro inteligente. (gcc hace un código más rápido, 0.052 para esta solución y 0.09s para el enfoque de registro inteligente).
Una implementación snprintf
correcta:
int count = snprintf(NULL, 0, "%i", x);
longitud de n:
length = ( i==0 ) ? 1 : (int)log10(n)+1;
sigue dividiendo entre diez hasta que obtienes cero, y luego solo muestra el número de divisiones.
int intLen(int x)
{
if(!x) return 1;
int i;
for(i=0; x!=0; ++i)
{
x /= 10;
}
return i;
}
sprintf(s, "%d", n);
length_of_int = strlen(s);
int digits=1;
while (x>=10){
x/=10;
digits++;
}
return digits;
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;
}
int intlen(int integer){
int a;
for(a = 1; integer /= 10; a++);
return a;
}