Variables en Java — ejercicios para dominar tipos, casting y Strings

En la práctica ya provocamos los tres sustos clásicos de las variables en Java. Ahora toca resolver por tu cuenta — pero con un giro: los ejercicios de aquí no van a poner el foco exactamente en lo mismo que la práctica. La división entera, el casting y el == aparecen, pero como herramientas para resolver algo, no como el protagonista. Eso es lo que pasa en los exámenes reales.

Tres niveles, tres contextos distintos. Intenta resolverlos antes de mirar la solución — aunque sea 10 minutos peleando con el compilador. Ese rato es donde ocurre el aprendizaje de verdad.


Variables en Java ejercicios — Nivel básico

Ejercicio 1 — Calculadora de IMC

Escribe un programa que pida el peso en kg y la altura en metros, calcule el Índice de Masa Corporal y muestre el resultado con su clasificación. Incluye también el peso ideal para esa altura.

El IMC se calcula así: IMC = peso / (altura × altura)

Salida esperada con 70 kg y 1.75 m:

=== CALCULADORA DE IMC ===

Peso (kg): 70
Altura (m): 1.75

--- Resultado ---
IMC:             22,86
Clasificación:   Normopeso
Peso ideal:      entre 56,7 kg y 80,1 kg
Rango saludable: 18,5 - 24,9

Estado: ✓ Tu peso está dentro del rango saludable

Clasificaciones:

IMC < 18.5          → Bajo peso
IMC entre 18.5-24.9 → Normopeso
IMC entre 25-29.9   → Sobrepeso
IMC >= 30           → Obesidad

Peso ideal: el rango corresponde a IMC 18.5 y 24.9 para esa altura.

💡 Pistas:

  • altura * altura — no existe altura^2 en Java, eso es XOR bit a bit. Para potencias usa Math.pow(altura, 2) o simplemente multiplica
  • El peso ideal mínimo es 18.5 * altura * altura y el máximo 24.9 * altura * altura
  • Usa if/else if en cadena para la clasificación — no switch, porque estás comparando rangos de double

Variables en Java ejercicios — Nivel intermedio

Ejercicio 2 — Conversor de tiempo

Escribe un programa que pida un número de segundos totales y lo descomponga en días, horas, minutos y segundos. Muestra también el porcentaje que representa dentro de un día completo.

Salida esperada con 90061 segundos:

=== CONVERSOR DE TIEMPO ===

Segundos totales: 90061

--- Desglose ---
1 día, 1 hora, 1 minuto y 1 segundo

--- En detalle ---
Días:     1    (86400 segundos)
Horas:    1    (3600 segundos)
Minutos:  1    (60 segundos)
Segundos: 1

--- Porcentaje del día ---
90061 segundos = 104,24% de un día completo
(más de un día completo)

💡 Pistas:

  • Este ejercicio es todo división entera y módulo — no necesitas ningún double hasta el porcentaje final
  • El orden importa: primero calcula días (segundos / 86400), luego el resto (% 86400), luego horas de ese resto, y así
  • Para el porcentaje necesitas el cast: (double) segundos / 86400 * 100
  • Ojo con el texto: «1 hora» vs «2 horas» — singular y plural cambian. Usa el operador ternario

Variables en Java ejercicios — Desafío final

Ejercicio 3 — Tienda con productos

Escribe un programa completo que gestione la información de tres productos de una tienda. Para cada producto pide nombre, precio base y unidades en stock. El programa genera un informe con los precios con IVA (21%), el valor total del inventario y el producto más caro.

Salida esperada:

=== GESTIÓN DE TIENDA ===

--- Producto 1 ---
Nombre: Portátil
Precio base (€): 899.99
Stock: 5

--- Producto 2 ---
Nombre: Ratón
Precio base (€): 29.99
Stock: 23

--- Producto 3 ---
Nombre: Teclado
Precio base (€): 79.99
Stock: 12

╔═══════════════════════════════════════════════╗
║              INFORME DE INVENTARIO            ║
╠═══════════════╦═══════════╦════════╦══════════╣
║ Producto      ║ Base      ║ +IVA   ║ Stock    ║
╠═══════════════╬═══════════╬════════╬══════════╣
║ Portátil      ║  899,99 € ║1088,99€║        5 ║
║ Ratón         ║   29,99 € ║  36,29€║       23 ║
║ Teclado       ║   79,99 € ║  96,79€║       12 ║
╠═══════════════╩═══════════╩════════╩══════════╣
║ Valor total inventario:          6.384,88 €   ║
║ Producto más caro (sin IVA):     Portátil      ║
║ Producto más barato (sin IVA):   Ratón         ║
╚═══════════════════════════════════════════════╝

El valor total del inventario es la suma de precio × stock para cada producto.

💡 Pistas:

  • Declara arrays de tres posiciones: String[] nombres = new String[3], double[] precios = new double[3], int[] stocks = new int[3]
  • Para encontrar el más caro: empieza asumiendo que el primero es el más caro y recorre los demás comparando
  • El valor del inventario de cada producto es precios[i] * stocks[i] — mucho ojo con la división entera aquí si mezclas tipos
  • El sc.nextLine() de limpieza va después de sc.nextDouble() y sc.nextInt() — ya lo conoces

¿Qué falla aquí?

Antes de ver las soluciones, estos son los errores más frecuentes en este tipo de ejercicios. ¿Encuentras el problema en cada uno?

Error 1

int segundos = 90061;
double porcentaje = segundos / 86400 * 100;
System.out.printf("%.2f%%%n", porcentaje);
// Muestra: 100,00% en lugar de 104,24%

¿Lo ves? segundos / 86400 es división entera — da 1. Luego 1 * 100 = 100.0. El cast tiene que ir antes:

double porcentaje = (double) segundos / 86400 * 100;
// Ahora sí: 104,24%

Error 2

Scanner sc = new Scanner(System.in);
System.out.print("Nombre: ");
String nombre = sc.nextLine();
System.out.print("Precio: ");
double precio = sc.nextDouble();
System.out.print("Categoría: ");
String categoria = sc.nextLine(); // ← lee cadena vacía

Falta el sc.nextLine() de limpieza después del nextDouble(). La solución:

double precio = sc.nextDouble();
sc.nextLine(); // ← consume el \n sobrante
String categoria = sc.nextLine(); // ahora espera al usuario

Error 3

String cat = sc.nextLine().trim().toLowerCase();
if (cat == "electronica") {
    System.out.println("Categoría válida");
}
// Nunca entra en el if aunque escribas "electronica"

== compara referencias de memoria, no contenido. Siempre:

if (cat.equals("electronica")) { // ← correcto

Soluciones comentadas

Solución Ejercicio 1

import java.util.Scanner;

public class CalculadoraIMC {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("=== CALCULADORA DE IMC ===");
        System.out.println();

        System.out.print("Peso (kg): ");
        double peso = sc.nextDouble();

        System.out.print("Altura (m): ");
        double altura = sc.nextDouble();

        // Calculamos el IMC — ojo: no existe ^ en Java para potencias
        // altura * altura es lo más directo y claro para este caso
        // Math.pow(altura, 2) también funciona pero es excesivo aquí
        double imc = peso / (altura * altura);

        // Calculamos el rango de peso ideal para esta altura
        // multiplicamos por el IMC límite, no al revés
        double pesoMinimo = 18.5 * (altura * altura);
        double pesoMaximo = 24.9 * (altura * altura);

        // Clasificación — usamos if/else if porque comparamos rangos de double
        // switch no sirve aquí: solo funciona con valores exactos, no rangos
        String clasificacion;
        if (imc < 18.5) {
            clasificacion = "Bajo peso";
        } else if (imc < 25.0) {
            clasificacion = "Normopeso";      // entre 18.5 y 24.9
        } else if (imc < 30.0) {
            clasificacion = "Sobrepeso";      // entre 25 y 29.9
        } else {
            clasificacion = "Obesidad";       // 30 o más
        }

        // Determinamos si está en rango saludable — boolean limpio
        boolean saludable = (imc >= 18.5 && imc < 25.0);

        System.out.println();
        System.out.println("--- Resultado ---");
        // %.2f para mostrar dos decimales — el IMC no necesita más precisión
        System.out.printf("IMC:             %.2f%n", imc);
        System.out.printf("Clasificación:   %s%n", clasificacion);
        System.out.printf("Peso ideal:      entre %.1f kg y %.1f kg%n",
                          pesoMinimo, pesoMaximo);
        System.out.printf("Rango saludable: 18,5 - 24,9%n");
        System.out.println();

        // El operador ternario aquí es más compacto que un if/else
        // si la condición es simple, el ternario lo hace más legible
        System.out.printf("Estado: %s%n",
            saludable
            ? "✓ Tu peso está dentro del rango saludable"
            : "⚠ Tu peso está fuera del rango saludable");

        sc.close();
    }
}

Solución Ejercicio 2

import java.util.Scanner;

public class ConversorTiempo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("=== CONVERSOR DE TIEMPO ===");
        System.out.println();

        System.out.print("Segundos totales: ");
        int totalSegundos = sc.nextInt();

        // Todo esto es división entera y módulo — sin doubles hasta el final
        // El orden importa: primero los valores más grandes

        // ¿Cuántos días completos caben?
        int dias = totalSegundos / 86400;         // 86400 = 60*60*24
        int resto = totalSegundos % 86400;        // lo que sobra tras quitar los días

        // De lo que sobra, ¿cuántas horas completas?
        int horas = resto / 3600;                 // 3600 = 60*60
        resto = resto % 3600;                     // reutilizamos la variable resto

        // De lo que queda, ¿cuántos minutos completos?
        int minutos = resto / 60;
        int segundos = resto % 60;                // lo que sobra son segundos

        System.out.println();
        System.out.println("--- Desglose ---");

        // Singular/plural con ternario — pequeño detalle que marca la diferencia
        System.out.printf("%d %s, %d %s, %d %s y %d %s%n",
            dias,    (dias == 1    ? "día"    : "días"),
            horas,   (horas == 1   ? "hora"   : "horas"),
            minutos, (minutos == 1 ? "minuto" : "minutos"),
            segundos,(segundos == 1? "segundo": "segundos"));

        System.out.println();
        System.out.println("--- En detalle ---");
        System.out.printf("Días:     %-4d (86400 segundos)%n", dias);
        System.out.printf("Horas:    %-4d (3600 segundos)%n",  horas);
        System.out.printf("Minutos:  %-4d (60 segundos)%n",    minutos);
        System.out.printf("Segundos: %d%n",                     segundos);

        System.out.println();
        System.out.println("--- Porcentaje del día ---");

        // Aquí sí necesitamos double — y el cast va ANTES de dividir
        // Si escribiéramos totalSegundos / 86400 * 100, la división entera
        // truncaría el resultado antes de que el double entre en juego
        double porcentaje = (double) totalSegundos / 86400 * 100;

        System.out.printf("%d segundos = %.2f%% de un día completo%n",
                          totalSegundos, porcentaje);

        // Mensaje adicional según el resultado
        if (porcentaje > 100) {
            System.out.println("(más de un día completo)");
        } else if (porcentaje == 100) {
            System.out.println("(exactamente un día completo)");
        } else {
            System.out.printf("(faltan %.2f%% para completar el día)%n",
                              100 - porcentaje);
        }

        sc.close();
    }
}

Solución Ejercicio 3

import java.util.Scanner;

public class GestionTienda {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("=== GESTIÓN DE TIENDA ===");
        System.out.println();

        // Arrays para los tres productos — mismo índice = mismo producto
        // Declaramos el tamaño fijo porque sabemos que son 3 productos
        int numProductos = 3;
        String[] nombres = new String[numProductos];
        double[] precios = new double[numProductos];
        int[]    stocks  = new int[numProductos];

        // Recogemos los datos de cada producto con un bucle
        // i va de 0 a 2 — los arrays en Java empiezan en 0, no en 1
        for (int i = 0; i < numProductos; i++) {
            System.out.printf("--- Producto %d ---%n", i + 1); // mostramos 1,2,3 al usuario
            System.out.print("Nombre: ");
            nombres[i] = sc.nextLine();

            System.out.print("Precio base (€): ");
            precios[i] = sc.nextDouble();
            sc.nextLine(); // limpiamos el \n — ya sabes por qué

            System.out.print("Stock: ");
            stocks[i] = sc.nextInt();
            sc.nextLine(); // otro \n sobrante
            System.out.println();
        }

        // Calculamos el IVA y el valor de inventario de cada producto
        double IVA = 0.21;
        double[] preciosConIVA    = new double[numProductos];
        double[] valorInventario  = new double[numProductos];
        double   totalInventario  = 0;

        for (int i = 0; i < numProductos; i++) {
            preciosConIVA[i]   = precios[i] * (1 + IVA);
            // stocks[i] es int, precios[i] es double
            // la multiplicación int*double da double automáticamente — widening
            valorInventario[i] = precios[i] * stocks[i];
            totalInventario   += valorInventario[i];
        }

        // Buscamos el más caro y el más barato
        // Estrategia: empezamos asumiendo que el primero es el extremo
        // y recorremos los demás para ver si hay alguno mayor/menor
        int indiceMasCaro   = 0;
        int indiceMasBarato = 0;
        for (int i = 1; i < numProductos; i++) {
            if (precios[i] > precios[indiceMasCaro]) {
                indiceMasCaro = i;   // encontramos uno más caro
            }
            if (precios[i] < precios[indiceMasBarato]) {
                indiceMasBarato = i; // encontramos uno más barato
            }
        }

        // Mostramos el informe formateado
        System.out.println("╔═══════════════════════════════════════════════╗");
        System.out.println("║              INFORME DE INVENTARIO            ║");
        System.out.println("╠═══════════════╦═══════════╦════════╦══════════╣");
        System.out.println("║ Producto      ║ Base      ║ +IVA   ║ Stock    ║");
        System.out.println("╠═══════════════╬═══════════╬════════╬══════════╣");

        for (int i = 0; i < numProductos; i++) {
            // %-13s alinea a la izquierda con 13 chars — los nombres quedan alineados
            System.out.printf("║ %-13s ║ %7.2f € ║%6.2f€║ %8d ║%n",
                nombres[i], precios[i], preciosConIVA[i], stocks[i]);
        }

        System.out.println("╠═══════════════╩═══════════╩════════╩══════════╣");
        System.out.printf( "║ Valor total inventario:       %12.2f €   ║%n",
                           totalInventario);
        System.out.printf( "║ Producto más caro (sin IVA):  %-14s ║%n",
                           nombres[indiceMasCaro]);
        System.out.printf( "║ Producto más barato (sin IVA):%-14s ║%n",
                           nombres[indiceMasBarato]);
        System.out.println("╚═══════════════════════════════════════════════╝");

        sc.close();
    }
}

Visualízalo con Python Tutor

Selecciona Java en el desplegable y pega en pythontutor.com:

public class Demo {
    public static void main(String[] args) {
        // División entera vs cast correcto
        int segundos = 90061;

        // MAL — división entera antes del cast
        double malPorcentaje = segundos / 86400 * 100;

        // BIEN — cast antes de dividir
        double bienPorcentaje = (double) segundos / 86400 * 100;

        System.out.printf("Mal:  %.2f%%%n", malPorcentaje);
        System.out.printf("Bien: %.2f%%%n", bienPorcentaje);

        // Búsqueda del máximo en un array
        double[] precios = {899.99, 29.99, 79.99};
        int indiceMasCaro = 0;
        for (int i = 1; i < precios.length; i++) {
            if (precios[i] > precios[indiceMasCaro]) {
                indiceMasCaro = i;
            }
        }
        System.out.println("Más caro en índice: " + indiceMasCaro);
        System.out.println("Precio: " + precios[indiceMasCaro]);
    }
}

Ejecuta paso a paso y observa dos momentos clave. Cuando se evalúa segundos / 86400 * 100, Python Tutor muestra que segundos / 86400 da 1 — entero — antes de que el resultado se asigne al double. El daño ya está hecho. En la segunda versión, el cast convierte segundos a 104156.0 antes de dividir y todo fluye como decimal. En el bucle de búsqueda del máximo, observa cómo indiceMasCaro empieza en 0 y solo cambia cuando encontramos un precio mayor — al final apunta al índice correcto sin necesidad de guardar el precio máximo por separado.


Chuletario — variables en Java

// ============================================
// CHULETARIO — Variables en Java
// Sergio Learns · sergiolearns.com
// ============================================

// TIPOS PRIMITIVOS — los que usarás en FP2
int     i = 42;          // enteros — el más común
double  d = 3.14;        // decimales — siempre double, no float
boolean b = true;        // true o false — en minúsculas
char    c = 'A';         // un carácter — comillas simples

// CONSTANTES — no cambian después de asignarse
final double PI        = 3.14159;
final int    MAX_ITEMS = 100;

// STRING — clase, no primitivo
String s = "hola";
// Métodos más usados:
s.length()               // longitud
s.charAt(0)              // carácter en posición 0
s.toUpperCase()          // todo mayúsculas
s.toLowerCase()          // todo minúsculas
s.trim()                 // quita espacios al inicio y final
s.equals("hola")         // compara contenido — SIEMPRE esto
s.equalsIgnoreCase("HOLA") // igual pero sin importar mayúsculas

// LA REGLA DE ORO DE LOS STRINGS
s1.equals(s2)    // ← CORRECTO — compara contenido
s1 == s2         // ← PELIGROSO — compara referencias de memoria

// WIDENING — automático, de menor a mayor tipo
int    → long → double   // Java lo hace solo, no hace falta cast

// NARROWING — manual, de mayor a menor tipo — puede perder datos
double d = 9.99;
int    i = (int) d;      // → 9  (trunca, NO redondea)
// Para redondear: (int) Math.round(d) → 10

// LA TRAMPA DE LA DIVISIÓN ENTERA
int a = 7, b = 2;
int    mal   = a / b;              // → 3    (entera)
double bien  = (double) a / b;     // → 3.5  (cast ANTES)
double trampa = (double)(a / b);   // → 3.0  (cast DESPUÉS — ya es tarde)

// MÓDULO Y DIVISIÓN ENTERA — muy útiles juntos
int total = 90061;
int dias    = total / 86400;   // cuántos días completos
int resto   = total % 86400;   // lo que sobra tras quitar los días
int horas   = resto  / 3600;   // cuántas horas del resto
// ... y así hasta los segundos

// SCANNER — trampa del nextLine() después de nextInt/nextDouble
int edad = sc.nextInt();
sc.nextLine();             // ← SIEMPRE después de nextInt/nextDouble
String nombre = sc.nextLine();  // sin el nextLine() anterior, esto lee ""

// VALORES LÍMITE — útiles para detectar overflow
Integer.MAX_VALUE   // 2.147.483.647 — máximo int
Integer.MIN_VALUE   // -2.147.483.648 — mínimo int
Double.MAX_VALUE    // número positivo más grande en double

// OPERADOR TERNARIO — para condiciones simples en una línea
String texto = (condicion) ? "valor si true" : "valor si false";
// Ejemplo:
String plural = (dias == 1) ? "día" : "días";

// PRINTF — especificadores más usados
%d    → int
%f    → double  (%.2f = 2 decimales)
%s    → String
%c    → char
%b    → boolean
%n    → salto de línea en printf
%%    → % literal
%10d  → alineado a la derecha, 10 chars
%-10s → alineado a la izquierda, 10 chars

// MATH — funciones matemáticas más usadas
Math.abs(x)         // valor absoluto
Math.pow(x, 2)      // x elevado a 2
Math.sqrt(x)        // raíz cuadrada
Math.round(x)       // redondeo al entero más cercano
Math.max(a, b)      // el mayor de dos valores
Math.min(a, b)      // el menor de dos valores
Sigue aprendiendoTodos los artículos de Java

Sigue aprendiendo

Un comentario

Deja una respuesta

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