elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Arreglado, de nuevo, el registro del warzone (wargame) de EHN


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Como calcular cuantos dígitos tiene un entero
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Como calcular cuantos dígitos tiene un entero  (Leído 7,097 veces)
kutcher

Desconectado Desconectado

Mensajes: 53


Ver Perfil
Como calcular cuantos dígitos tiene un entero
« en: 24 Julio 2014, 22:02 pm »

Buenas, estoy codificando un programa y me urge saber cuantos dígitos tiene un
número que es de tipo int por ejem:

15742 = 5 dígitos
1234 = 4 dígitos
13 = 2 dígitos

He probado con sizeof pero no funciona ¿Alguien tiene alguna idea de como hacer esto?


En línea

ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #1 en: 24 Julio 2014, 22:15 pm »

sizeof() retorna el tamaño en bytes de una variable.

Ahora al tema, dado que el entero no guarda decimales, simplemente se pierden, puedes dividirlo entre 10 X veces, hasta que sea 0. En ese momento, X será el número de cifras que tendrá.


En línea

Blaster

Desconectado Desconectado

Mensajes: 190


Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #2 en: 24 Julio 2014, 22:25 pm »

¿Alguien tiene alguna idea de como hacer esto?

Otra opción seria aplicar el logaritmo (en base 10) al número del que deseas saber las cifras y luego sumarle uno:

Log(1)=>0
Log(9)=>0,95
Log(10)=>1
Log(11)=>1,04

Código
  1. digitos = log10(num) + 1

En digitos tendrás el número de cifras de num

Saludos
En línea

leosansan


Desconectado Desconectado

Mensajes: 1.314


Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #3 en: 25 Julio 2014, 00:02 am »

Buenas, estoy codificando un programa y me urge saber cuantos dígitos tiene un
número que es de tipo int
 ...........................

Por ejemplo, como comentó ivancea96:

Código
  1.  int digitos , n = 123456789 ;
  2.  for ( digitos = 0 ; n ; digitos++ , n /= 10 ) ;
  3.  printf ( "%d" , digitos ) ;

¡¡¡¡ Saluditos! ..... !!!!


« Última modificación: 25 Julio 2014, 00:13 am por leosansan » En línea

kutcher

Desconectado Desconectado

Mensajes: 53


Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #4 en: 25 Julio 2014, 00:39 am »

Gracias a todos por responder, voy aprobar el método que expuso Blaster me llamo la atención ¿nosé si es seguro esto? 
En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #5 en: 25 Julio 2014, 01:00 am »

De que es seguro, dará seguramente la respuesta, si tienes dudas al respecto recomiendo revisar los temas de exponencial y logaritmo para resolver dudas puntuales sobre ello :P

Aunque yo preferiría el metodo de leosansan ya aunque es mas largo en códigos es menos exigente en procesasor
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
Blaster

Desconectado Desconectado

Mensajes: 190


Ver Perfil
Re: Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #6 en: 25 Julio 2014, 03:11 am »

¿nosé si es seguro esto? 

Es un metodo matemático muy preciso ten por seguro que obtendrás el resultado esperado.
 
Aunque yo preferiría el metodo de leosansan ya aunque es mas largo en códigos es menos exigente en procesasor

Lo dudo aunque así fuera la diferencia seria mínima
En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #7 en: 25 Julio 2014, 03:39 am »

Lo dudo aunque así fuera la diferencia seria mínima

bueno, si es para un calculo independiente, efectivamente la diferencia es instrumental, pero para calcularlo múltiples veces, la diferencia de tiempo si es notable, ya que es la diferencia entre un ciclo con una división (operacion matematica simple posible de hacer por el procesador con un solo paso) contra logaritmo (intenta sacarlo solo con suma, resta, división y multiplicación para que veas cuantos pasos toma)

de resto, ya es cosa de kutcher que escoja que se le hace más mejor para su programa :P
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #8 en: 25 Julio 2014, 09:32 am »

ya que es la diferencia entre un ciclo con una división (operacion matematica simple posible de hacer por el procesador con un solo paso)

Perdón por la intromisión, pero la división es la operación más costosa con diferencia de las interpretadas como básicas: suma, resta, producto, división. Y cuando digo costosa me refiero en una proporción que puede llegar a ser de 8 a 1.

Dicho esto me ha surgido la duda de saber cual era el algoritmo más óptimo... manos a la obra salió algo tal que:

Código
  1. #include <iostream>
  2. #include <chrono>
  3. #include <math.h>
  4.  
  5. int DigitosV1( int numero )
  6. {
  7.  int digitos;
  8.  for ( digitos = 0; numero > 0; digitos++, numero /= 10 ) ;
  9.  return digitos;
  10. }
  11.  
  12. int DigitosV2( int numero )
  13. {
  14.  return log( numero ) + 1;
  15. }
  16.  
  17. const int NUMERO = 1234567890;
  18. const int MAXBUCLE = 1000000000;
  19.  
  20. int main( )
  21. {
  22.  int temp;
  23.  std::chrono::time_point<std::chrono::system_clock> start, end;
  24.  start = std::chrono::system_clock::now( );
  25.  for ( int i=0; i < MAXBUCLE; i++ )
  26.  {
  27.    temp = DigitosV1( NUMERO );
  28.  }
  29.  end = std::chrono::system_clock::now();
  30.  
  31.  std::chrono::duration<double> elapsed_seconds = end-start;
  32.  
  33.  std::cout << "Tiempo division: " << elapsed_seconds.count() << "s\n";
  34.  
  35.  start = std::chrono::system_clock::now( );
  36.  for ( int i=0; i < MAXBUCLE; i++ )
  37.  {
  38.    temp = DigitosV2( NUMERO );
  39.  }
  40.  end = std::chrono::system_clock::now();
  41.  
  42.  elapsed_seconds = end-start;
  43.  
  44.  std::cout << "Tiempo logaritmo: " << elapsed_seconds.count() << "s\n";
  45. }
  46.  

¿Qué sucede con los resultados? Son contundentes (aviso, abstenerse personas sensibles):

Editado: Estos resultados son con el programa compilado en modo debug... lo siento.

Código:
Tiempo division: 43.1613s
Tiempo logaritmo: 29.538s

Luego por 5 cabezas de ventaja, la opción del logaritmo es más óptima que la opción de la división.



Edito: Para probar opciones menos extremistas, he reducido el número de prueba a uno con 5 dígitos y he ejecutado el programa... los resultados son los siguientes:

Editado: Estos resultados son con el programa compilado en modo debug... lo siento.

Código:
Tiempo division: 19.1429s
Tiempo logaritmo: 29.564s

Se ve por tanto que la opción del logaritmo es estable en el tiempo, mientras que la división, obviamente, ha reducido su tiempo a la mitad ( tiene la mitad de dígitos ).

Dicho esto me surgió una nueva duda... log trabaja con "double"... y si la idea es trabajar con números más grandeS??

Un poco de refactorización y listo:

Código
  1. #include <iostream>
  2. #include <chrono>
  3. #include <limits>
  4. #include <math.h>
  5.  
  6. const int INT5 = 12345;
  7. const int INT7 = 1234567;
  8. const int INT10 = 1234567890;
  9.  
  10. const double DOUBLE5 = 12345.0;
  11. const double DOUBLE7 = 1234567.0;
  12. const double DOUBLE10 = 1234567890.0;
  13.  
  14. template< class T >
  15. int DigitosDIV( T numero )
  16. {
  17.  int digitos;
  18.  T divisor = 10;
  19.  T min = 1; // para que el bucle funcione con decimales
  20.  for ( digitos = 0; numero >= min; digitos++, numero /= divisor ) ;
  21.  return digitos;
  22. }
  23.  
  24. template< class T >
  25. int DigitosLOG( T numero )
  26. {
  27.  return log( numero ) + 1;
  28. }
  29.  
  30. template< class T >
  31. std::chrono::duration< double > Bucle( T numero, int(*func)(T) )
  32. {
  33.  int temp;
  34.  
  35.  auto start = std::chrono::system_clock::now( );
  36.  
  37.  const int max = std::numeric_limits< int >::max( );
  38.  for ( int i=0; i < max; i++ )
  39.  {
  40.    temp = func( numero );
  41.  }
  42.  auto end = std::chrono::system_clock::now( );
  43.  
  44.  return end - start;
  45. }
  46.  
  47. int main( )
  48. {
  49.  auto DivInt5  = Bucle( INT5,  DigitosDIV< int > );
  50.  auto DivInt7  = Bucle( INT7,  DigitosDIV< int > );
  51.  auto DivInt10 = Bucle( INT10, DigitosDIV< int > );
  52.  
  53.  auto LogInt5  = Bucle( INT5,  DigitosLOG< int > );
  54.  auto LogInt7  = Bucle( INT7,  DigitosLOG< int > );
  55.  auto LogInt10 = Bucle( INT10, DigitosLOG< int > );
  56.  
  57.  auto DivDouble5  = Bucle( DOUBLE5,  DigitosDIV< double > );
  58.  auto DivDouble7  = Bucle( DOUBLE7,  DigitosDIV< double > );
  59.  auto DivDouble10 = Bucle( DOUBLE10, DigitosDIV< double > );
  60.  
  61.  auto LogDouble5  = Bucle( DOUBLE5,  DigitosLOG< double > );
  62.  auto LogDouble7  = Bucle( DOUBLE7,  DigitosLOG< double > );
  63.  auto LogDouble10 = Bucle( DOUBLE10, DigitosLOG< double > );
  64.  
  65.  std::cout << "Tiempo division (int 5):     " << DivInt5.count( )     << " s\n";
  66.  std::cout << "Tiempo division (int 7):     " << DivInt7.count( )     << " s\n";
  67.  std::cout << "Tiempo division (int 10):    " << DivInt10.count( )    << " s\n\n";
  68.  std::cout << "Tiempo log (int 5):          " << LogInt5.count( )     << " s\n";
  69.  std::cout << "Tiempo log (int 7):          " << LogInt7.count( )     << " s\n";
  70.  std::cout << "Tiempo log (int 10):         " << LogInt10.count( )    << " s\n\n";
  71.  std::cout << "Tiempo division (double 5):  " << DivDouble5.count( )  << " s\n";
  72.  std::cout << "Tiempo division (double 7):  " << DivDouble7.count( )  << " s\n";
  73.  std::cout << "Tiempo division (double 10): " << DivDouble10.count( ) << " s\n\n";
  74.  std::cout << "Tiempo log (double 5):       " << LogDouble5.count( )  << " s\n";
  75.  std::cout << "Tiempo log (double 7):       " << LogDouble7.count( )  << " s\n";
  76.  std::cout << "Tiempo log (double 10):      " << LogDouble10.count( ) << " s\n\n";
  77. }

Y su correspondiente resultado (ahora sí en modo release):

Código
  1. Tiempo division (int 5):     23.6144 s
  2. Tiempo division (int 7):     33.9994 s
  3. Tiempo division (int 10):    49.798 s
  4.  
  5. Tiempo log (int 5):          60.28 s
  6. Tiempo log (int 7):          60.415 s
  7. Tiempo log (int 10):         60.8651 s
  8.  
  9. Tiempo division (double 5):  81.3541 s
  10. Tiempo division (double 7):  113.471 s
  11. Tiempo division (double 10): 162.253 s
  12.  
  13. Tiempo log (double 5):       60.7651 s
  14. Tiempo log (double 7):       60.8521 s
  15. Tiempo log (double 10):      60.7481 s

La conclusión final... cada uno que saque las suyas... pero simplificando yo obtengo las siguientes:

* El logaritmo es más estable... ideal para tareas de tiempo real.
* La división es, de media, más rápida si se trabaja con enteros... el logaritmo es más eficiente con decimales.
* Es curioso como se nota la bajada de tiempos de la división en modo release frente a modo debug
« Última modificación: 25 Julio 2014, 11:47 am por eferion » En línea

leosansan


Desconectado Desconectado

Mensajes: 1.314


Ver Perfil
Re: Como calcular cuantos dígitos tiene un entero
« Respuesta #9 en: 3 Agosto 2014, 23:46 pm »

Otra opción seria aplicar el logaritmo (en base 10) al número del que deseas saber las cifras y luego sumarle uno:

Log(1)=>0
Log(9)=>0,95
Log(10)=>1
Log(11)=>1,04

Código
  1. digitos = log10(num) + 1

En digitos tendrás el número de cifras de num

Saludos


Sólo una pequeña observación y es la referida a la importancia de trabajar con double si hay operaciones tipo producto o división implicadas.

Me explico con un simple ejemplo. Si queremos las cifras del resultado de 3 * 5 sin hacerlo podemos aplicar la propiedad de que el logaritmo de un producto es la suma de los logaritmos y, si estamos trabajando con enteros, el resultado sería:

Código
  1. digitos ( 3 * 5) =  log10 ( 3 * 5 ) = log10 (3) + log10 (5) + 1  = 0 + 0 + 1 = 1

En contra de lo que sabemos, 3 * 5 = 15 que tiene dos cifras. Lo anterior se evita trabajando don double, ya que entonces :

Código
  1. digitos ( 3 * 5) =  log10 ( 3 * 5 ) = log10 (3) + log10 (5) + 1  ==  2.176091

 y tan sólo hay que tomar la parte entera para obtener el resultado deseado.

Código
  1. n_digitos 3 * 5 = 2.176091 ==> de aqui tomamos la parte entera :
  2. n_digitos 3 * 5 = 2
  3.  

Parece una nimiedad lo que comento ya que podíamos haber multiplicado previamente y aplicado el log10 en forma entera al resultado de 15.

¿Pero es esto siempre posible?. Pongo un caso práctico: calcular las cifras que tiene 1500!. En este caso no es tan simple obtener el resultado numérico y ojo que no digo que no sea posible hacerlo en C, incluso sin librerías externas, que sí que se puede. Pero como un factorial no es más que un producto se puede calcular la cifra como suma de logaritmos pero en tipo flotante y el resultado final pasarlo a entero obteniendo:

Código
  1. n_digitos [ 1500! ] = 4115.682325
  2.  
  3. n_digitos [ 1500! ] = 4115 ---> PERFECTO <----
  4.  

Y la suma de los log10 se puede realizar con un simple for:

Código
  1. #include <stdio.h>
  2. #include <math.h>
  3. #define N  1500
  4.  
  5. int main( ) {
  6.  double n_digitos = 1 ;
  7.  int digitos , i ;
  8.  for( i = 1 ; i <= N ; i++ )
  9.    n_digitos += ( log10 ( i ) ) ;
  10.  printf( "n_digitos [ 1500! ] = %lf\n\n" , n_digitos );
  11.  digitos = ( int ) n_digitos ;
  12.  printf( "n_digitos [ 1500! ] = %d\n\n" , digitos );
  13.  return 0;
  14. }

Y conste que empieza el for en 1 innecesariamente ya que su log es cero, por lo que podía haber empezado en 2, pero es por ponerlo "bonito".  ;)

Como comenté al principio, se trataba de una simple observación en la diferencia, y obligación en según qué casos, de trabajar con enteros o flotantes para no equivocar el resultado del cálculo del número de dígitos.

¡¡¡¡ Saluditos! ..... !!!!


« Última modificación: 3 Agosto 2014, 23:55 pm por leosansan » En línea

Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
necesito saber como ingresar 1 nº entero >0 y <=100 luego contar sus digitos.... « 1 2 »
Ejercicios
dpunisher03 18 17,095 Último mensaje 28 Mayo 2009, 08:24 am
por Eliptico
Como saber cuantos Km tiene de alcance una antena WiFi ?
Materiales y equipos
Dark Knight 4 25,419 Último mensaje 22 Octubre 2008, 23:21 pm
por Dark Knight
Cuantos años tiene su cerebro.? « 1 2 3 4 »
Foro Libre
Nirvanareus 35 17,505 Último mensaje 4 Diciembre 2010, 10:11 am
por flacc
cuantos años tiene eso web?
Foro Libre
ami89 4 3,674 Último mensaje 27 Junio 2010, 22:31 pm
por [Decoded]
Como cuento cuantos numeros tiene un archivo en (C)
Programación C/C++
andie13 3 2,969 Último mensaje 16 Noviembre 2016, 20:10 pm
por MRx86
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines