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

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 Java. 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étodo principal

El método principal tendrá como objetivo la lectura de datos e invocación al método \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 Java la realizaremos a través de la clase \texttt{Scanner} y el valor leído se almacenará en la variable \texttt{numero}. Recuerde que para poder usar la clase \texttt{Scanner}, debemos importarla desde \texttt{java.util.Scanner}. Para la lectura usamos el método \texttt{nextInt}.

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 numero 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 (numero>0). Para obtener el valor absoluto de un número usamos método \texttt{abs}. El método \texttt{abs} debemos importarlo de \texttt{java.lang.Math.abs}.

package cuenta_digitos_v1;

import static java.lang.Math.abs;
import java.util.Scanner;

public class Cuenta_Digitos_v1 {

    public static void main(String[] args) {
        int numero;
        Scanner reader = new Scanner(System.in);
        System.out.printf("Ingrese un número: ");
        numero = reader.nextInt();

        numero = abs(numero);
        System.out.printf("El número tiene %d dígito(s)%n", cuenta_digitos(numero));
    }
} 

Cuenta dígitos

Procederemos ahora a implementar el método \texttt{cuenta\_digitos}. Este método recibe como parámetro un número natural \texttt{numero} 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étodo \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{numero}. Usaremos a \texttt{numero} 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{numero>0}. Cuando \texttt{numero} 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{numero}. Debemos quitarle un dígito a la variable de control \texttt{numero}. Esto se logra simplemente dividiendo entre 10 al número en cuestión. Utilizamos para este fin la operación de asignación \texttt{/=}. Recuerde que \texttt{numero/=10} equivale a \texttt{numero=numero/10}.
    private static int cuenta_digitos(int numero) {
        while (numero > 0) {

             numero /= 10;
        }
    } 

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. Para incrementar el contador hemos utilizado el operador de incremento \texttt{++}. Recuerde que \texttt{total\_digitos++} equivale a \texttt{total\_digitos=total\_digitos+1}.

    private static int cuenta_digitos(int numero) {
        int total_digitos = 0;
        while (numero > 0) {
            total_digitos++;
            numero /= 10;
        }
    } 

Caso particular del número 0

Hay un caso particular que debemos manejar en nuestro programa. Se da cuando el parámetro \texttt{numero} es igual a cero. Dado que en la versión iterativa implementada, usamos como condición de iteración \texttt{numero>0}, nunca se ejecutará cuando \texttt{numero=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.

    private static int cuenta_digitos(int numero) {
        int total_digitos = 0;
        while (numero > 0) {
            total_digitos++;
            numero /= 10;
        }
        if (total_digitos == 0) {
            total_digitos++;
        }
        return total_digitos;
    } 

Cuenta dígitos: versión con for

Como ya hemos comentado anteriormente en iterando++, la instrucción \texttt{for} en Java funciona de forma muy similar a una iterativa con entrada controlada. La principal diferencia es que la instrucción \texttt{for} la inicialización de la variable de control, la condición y la actualización de la variable de control, se realiza en un mismo lugar. Esta característica hace que sea una de las instrucciones preferidas para iterar de muchos programadores ya que facilita el entendimiento del código.

En este caso se ha utilizado la instrucción \texttt{ for ( ; numero > 0; numero /= 10)}. La parte de la inicialización está vacía dado que no se ha realizado ella pues usamos el parámetro como variable de control. La condición es \texttt{numero>0} y la actualización de la variable de control es \texttt{numero /= 10}.

    private static int cuenta_digitos(int numero) {
        int total_digitos = 0;
        for (; numero > 0; numero /= 10) {
            total_digitos++;
        }
        if (total_digitos == 0) {
            total_digitos++;
        }
        return total_digitos;
    } 

Cuenta dígitos: versión con do-while

Lorem fistrum por la gloria de mi madre esse jarl aliqua llevame al sircoo. De la pradera ullamco qué dise usteer está la cosa muy malar.

    private static int cuenta_digitos(int numero) {
        int total_digitos = 0;
        do {
            total_digitos++;
            numero /= 10;
        } while (numero > 0);
        return total_digitos;
    } 

Cuenta dígitos: versión recursiva

Método recursivo

La siguiente versión que implementaremos será la versión recursiva. El caso base será cuando \texttt{numero==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{numero}. El parámetro \texttt{n} lo dividimos entre 10 antes de hacer la invocación. 

    private static int cuenta_digitos(int numero) {
        if (numero == 0) {
            return 0;
        }
        return 1 + cuenta_digitos(numero / 10);
    } 

Método principal

La versión recursiva que hemos implementado posee un problema. No controla el caso cuando el \texttt{numero} pasado como parámetro es cero. En este situación hemos optado por hacer dicho control en el método principal. De esta forma si el número leído  es \texttt{0}, se imprime el valor de \texttt{1}. En caso contrario se imprime el valor que retorna el método recursivo. 

Hemos usado el operador ternario \texttt{?:} para realizar la condicional. El operador ternario posee 3 operandos. Funciona de forma muy similar a una selectiva. Si el primer operando se evalúa como verdadero, se retorna el segundo operando, en caso contrario se retorna el tercer operando. La ventaja que ofrece es que permite escribir condicionales de una forma muy simple en una línea.

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

package cuenta_digitos_v4;

import static java.lang.Math.abs;
import java.util.Scanner;

public class Cuenta_Digitos_v4 {

    public static void main(String[] args) {
        int numero;
        Scanner reader = new Scanner(System.in);
        System.out.printf("Ingrese un número: ");
        numero = reader.nextInt();

        numero = abs(numero);
        System.out.printf("El número tiene %d dígito(s)%n", numero == 0 ? 1 : cuenta_digitos(numero));
    }
} 

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.

    private static int cuenta_digitos(int numero) {
        if (numero == 0) {
            return 1;
        }
        return (int)log10(numero) + 1;
    } 

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. 

    private static int cuenta_digitos(int numero, int base) {
        if (numero == 0) {
            return 1;
        }
        return (int) (log(numero) / log(base)) + 1;
    } 

Conclusión

Hemos presentado en este artículo, 5 propuestas de solución al problema de contar dígitos de un número en Java. 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 PSeInt y otros lenguajes de programación. Te invitamos a leer los siguientes artículos de iterando++

Si te interesa profundizar en Java, el mejor libro que hay es Effective Java de Joshua Bloch. Uno de los libros favoritos de los que se inician en Java es Java: Learn Java in One Day and Learn It Well de  Jamie Chan.

Deja una respuesta

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