Cantidad de dígitos de un número en PSeInt

Más ejercicios resueltos

Si deseas revisar más ejercicios resueltos, haz click en el siguiente botón. 

A continuación presentamos 5 alternativas de solución al problema de contar la cantidad de dígitos de un número en PSeInt. Si deseas ver el enunciado del problema, haz click en el siguiente enlace

A continuación presentamos 5 alternativas de solución usando las distintas formas de la estructura algorítmica iterativa, la recursión, así como el uso de los logaritmos

Módulo principal

El módulo principal tendrá como objetivo la lectura de datos e invocación al módulo \texttt{cuenta\_digitos}. No existe ninguna validación que realizar al número n, esto debido a que el enunciado del problema indica que el dominio del número corresponde al conjunto de los números enteros. La lectura en PSeInt se realiza a través de la instrucción \texttt{Leer} y el valor leído se almacenará en la variable \texttt{n}.

Debido a que las distintas alternativas de solución que se analizarán, esperan que el número que se pase como parámetro sea un número natural, se actualiza el número n leído con su valor absoluto. ¿Por qué esto es necesario? Esto en realidad corresponde con el detalle de la implementación de cada alternativa de solución. Lo veremos más adelante en cada solución, pero lo que podemos ir adelantando es que todas ellas solo funcionarán para los números naturales (n>0). Para obtener el valor absoluto de un número usamos la función \texttt{abs}.

pseudocódigo cuenta dígitos - módulo principal
Módulo principal

Cuenta dígitos

Procederemos ahora a implementar el módulo \texttt{cuenta\_digitos}. Este módulo recibe como parámetro un número natural \texttt{n} mayor o igual a cero. Retorna la cantidad de dígitos del número pasado como parámetro.

Procederemos a presentar detalladamente la implementación del módulo \texttt{cuenta\_digitos} usando en primer lugar la estructura algorítmica iterativa con entrada controlada. Detallaremos tres puntos en particular:

  • El control de flujo.
  • El conteo de los dígitos.
  • El tratamiento del número cero.

Control de flujo

Como en todo problema iterativo, el primer punto a gestionar es el control de flujo. La versión que implementaremos se basa en la iteración y se busca que en cada iteración se cuenta un dígito del número que está siendo analizado. Entonces, ¿cómo realizamos el control de flujo? 

  1. Variable de control. El control de gestionaremos a través del mismo parámetro \texttt{n}. Usaremos a \texttt{n} como nuestra variable de control de la iteración.
  2. Condición de la iteración. Dado que queremos ir extrayendo un dígito en cada iteración, seguiremos iterando mientras existan dígitos para sacar. En otras palabras, mientras \texttt{n>0}. Cuando \texttt{n} contenga el valor de cero, asumiremos que no existirán más dígitos por extraer y la iteración deberá de terminar.
  3. Actualización de la variable de control. Al final de cada iteración debemos actualizar \texttt{n}. Debemos quitarle un dígito a la variable de control \texttt{n}. Esto se logra simplemente dividiendo entre 10 al número en cuestión. Solo un detalle a añadir. Debemos quedarnos solo con la parte entera de la división real por lo que usamos para este fin, la función \texttt{trunc}.
pseudocódigo cuenta dígitos - paso 1
Control de flujo

Conteo de dígitos

El siguiente paso es definir una variable en donde se llevará la cuenta de los dígitos que se van a ir extrayendo. Esta variable, comúnmente llamada contador, la hemos identificado con \texttt{total\_digitos}. Básicamente lo que hacemos es incrementar su valor en uno en cada iteración. Contando los dígitos que vamos obteniendo del número. 

pseudocódigo cuenta dígitos - paso 2
Conteo de dígitos

Caso particular del número 0

Hay un caso particular que debemos manejar en nuestro algoritmo. Se da cuando el parámetro \texttt{n} es igual a cero. Dado que en la versión iterativa implementada, usamos como condición de iteración \texttt{n>0}, nunca se ejecutará cuando \texttt{n=0}, por lo que la variable \texttt{total\_digitos} contendrá el valor de \texttt{0}. Entonces, en esta situación, asignamos el valor de \texttt{1} a la variable \texttt{total\_digitos}. Para esto usamos un estructura selectiva simple inmediatamente después del ciclo iterativo.

pseudocódigo cuenta dígitos - paso 3
Caso particular del número 0

Cuenta dígitos: versión con Repetir-Mientras

La versión que veremos ahora es la versión con salida controlada. Usaremos en este caso la instrucción \texttt{Repetir-Mientras}. A primera impresión es una versión muy parecida a la realizada con la instrucción \texttt{Mientras} pero como podrán notar, en esta versión no hacemos la verificación del caso particular del número 0. Pero, ¿por qué no es necesario? Dado que se realiza el control en la salida, el bloque de instrucciones se ejecutará por lo menos una vez. Entonces, aunque el parámetro \texttt{n} contenga el valor de 0, la iteración se ejecutará.

pseudocódigo cuenta dígitos - repetir mientras
Cuenta dígitos: versión con Repetir-Mientras

Cuenta dígitos: versión con Repetir-Hasta

Esta versión del algoritmo con \texttt{Repetir-Hasta} es my similar a la anterior. El único cambio significativo que existe es la condición de la iteración. En este caso, la condición no es para continuar iterarando sino para parar de repetir. Esta condición la hemos implementados a través de la expresión \texttt{n=0}. Lo que significa que cuando \texttt{n} es igual a cero, la iteración deja de repetir.

pseudocódigo cuenta dígitos - repetir hasta
Cuenta dígitos: versión con Repetir-Hasta

Cuenta dígitos: versión recursiva

Módulo recursivo

La siguiente versión que implementaremos será la versión recursiva. El caso base será cuando \texttt{n=0}. En esta situación se retorna el valor de \texttt{0}. En el caso recursivo se retorna \texttt{1} + la llamada recursiva pero actualizando el parámetro \texttt{n}. El parámetro \texttt{n} lo dividimos entre 10 antes de hacer la invocación. En este caso como PSeInt no ofrece la división entera, usamos la división real y luego truncamos el resultado.

pseudocódigo cuenta dígitos versión recursiva
Módulo recursivo

Módulo principal

La versión recursiva que hemos implementado posee un problema. No controla el caso cuando el número pasado como parámetro es cero. En este situación hemos optado por hacer dicho control en el módulo principal. De esta forma si la cantidad de dígitos retornada es \texttt{0}, se actualiza por el valor de \texttt{1}.

Otra opción que hubiésemos podido tomar en cuenta es encapsular esta verificación del cero en otro módulo. Haciendo transparente este detalle de implementación.

pseudocódigo cuenta dígitos recursivo- módulo principal
Módulo principal

Cuenta dígitos: versión usando logaritmos

Otra versión muy usada para contar la cantidad de dígitos de un número es la que utiliza logaritmos. Esta versión es muy simple de implementar pero antes de ello se debe entender qué se entiende por logaritmo.

Sea b un número real positivo no nulo distinto de 1, y x otro número positivo no nulo. Se denomina logaritmo del número x en la base b, al exponente l al que debe elevarse la base b para obtener dicho número x. El logaritmo se expresa de la siguiente manera \log_bx y si \log_bx =l \leftrightarrow b^l=x . Por ejemplo \log_{5}{625}=4 ya que 625=5^4=5 \times 5 \times 5 \times 5. El logaritmo es la operación inversa a la exponenciación.

Pues bien, ¿qué tienen que ver los logaritmos con la cantidad de dígitos de un número? Pues mucho. Veamos. Supongamos que tenemos el número 123. Si le aplicamos el logaritmo en base 10, obtenemos que \log_{10}{123} \approx 2.089905111 . Esto significa que 10^{2.089905111}=123. Probemos ahora con otro número, por ejemplo 654, \log_{10}{654} \approx 2.815577748 . Esto significa que 10^{2.815577748}=654. Ahora con 1000, \log_{10}{1000} = 3 . Esto significa que 10^{3}=1000.

Lo que el logaritmo en base 10 no está retornando es a cuanto debemos elevar 10 para que retorne el número en cuestión. Cómo sabemos que estamos usando el sistema de numeración decimal, es decir, en base 10.  Básicamente lo que el logaritmo no está respondiendo es cuántas potencias de 10 yo debo multiplicar para llegar a dicho número. Pero cada vez que usamos una potencia de 10, significa que el dígito posee un dígito adicional a dicha potencia. Por ejemplo, si yo puedo representar un número con 3 potencias de 10, significará que tendrá 4 dígitos, pues 10^3=1000. Si yo puedo representar un número con  2.089905111 potencias de 10, entonces se requerirán 3 dígitos. Y es esta la razón por la cual podemos obtener la cantidad de dígitos dado el logaritmo.

Basta aplicar el logaritmo en base 10, tomar su parte entera y sumarle 1. Lamentablemente PSeInt no implementa de forma nativa el logaritmo en base 10 por lo que tenemos que aplicar una de los teoremas de los logaritmos, el teorema del cambio de base. Según este teorema \log_bx=\frac{\log_ax}{\log_ab}. Esto significa que se puede basar el cálculo del logaritmo en cualquier base con el logaritmo de otra base. El PSeInt implementa únicamente el logaritmo natural a través de la función \texttt{ln} pero dividiendo entre \texttt{ln(10)} podemos obtener el logaritmo en base \texttt{10}.

pseudocódigo cuenta dígitos con logaritmos
Cuenta dígitos: versión usando logaritmos

Bonus track: cuenta dígitos en otra base

El logaritmo también se puede usar para contar la cantidad de dígitos que posee el número en otras bases. Simplemente en lugar de usar como base del logaritmo 10, usamos la base en la cual deseamos obtener la cantidad de dígitos.  

pseudocódigo cuenta dígitos en otra base con logaritmos
Bonus track: cuenta dígitos en otra base

Conclusión

Hemos presentado en este artículo, 5 propuestas de solución al problema de contar dígitos de un número en PSeInt. Se ha utilizado para el diseño algorítmico la técnica del diseño descendente y se ha controlado  el flujo en los módulos usando estructuras selectivas e iterativas. Podrá descargar la solución propuesta en el repositorio GitHub de iterando++ a través del siguiente enlace

Hemos preparado otros artículos adicionales en donde describimos al detalle la implementación de este problema en lenguajes de programación. Te invitamos a leer los siguientes artículos de iterando++

Si te interesa profundizar más sobre diseño algorítmico, te recomendamos el libro Foundations of Programming Languages de Kent D. D. Lee. En este libro encontrarás además información detallada sobre la programación orientada a objetos, funcional y lógica.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *