W3docs

Números en Java

Trabaja con tipos numéricos en Java — int, long, float, double — y comprende la precisión, el desbordamiento y la clase Number.

Java distingue entre números enteros y de punto flotante, y dentro de cada familia tiene varios tamaños. Elegir el tipo correcto es importante tanto para la corrección (precisión, rango) como para el rendimiento. Este capítulo es un recorrido enfocado por los tipos numéricos, sus literales, conversiones y los errores comunes que sorprenden a los principiantes. Asume que ya sabes cómo declarar una variable y has visto el conjunto completo de tipos de datos primitivos.

Los primitivos numéricos

TipoBitsRangoEstilo literal predeterminado
byte8-128 a 127byte b = 10;
short16-32.768 a 32.767short s = 30_000;
int32-2³¹ a 2³¹-1 (≈ ±2.100 millones)int i = 1_000_000;
long64-2⁶³ a 2⁶³-1long l = 9_000L;
float32IEEE 754 precisión simple (~7 dígitos)float f = 3.14f;
double64IEEE 754 precisión doble (~16 dígitos)double d = 3.14;

En el Java cotidiano:

  • Usa int para contadores, índices y la mayoría de los valores enteros.
  • Usa long cuando puedas superar ~2 mil millones (tamaños de archivo, milisegundos desde el epoch, generadores de ID).
  • Usa double para cálculos de punto flotante.
  • Usa float solo cuando la memoria sea limitada o una API lo requiera.

Literales enteros

Los dígitos simples son int:

int answer = 42;
int million = 1_000_000;     // underscores are ignored

Sufijo L (mayúscula preferida) para long:

long big = 9_000_000_000L;

Prefijo 0x para hexadecimal, 0b para binario, 0 para octal:

int hex = 0xFF;        // 255
int bin = 0b1010;      // 10
int oct = 0755;        // 493 — be careful, easy to write by accident

(Los literales octales son una fuente frecuente de errores — 0123 no es 123, es 83. Evita los ceros iniciales a menos que realmente quieras indicar octal.)

Literales de punto flotante

Los decimales simples son double:

double pi = 3.14159;
double e = 2.71828;

Sufijo f para float, d para double explícito (opcional):

float pif = 3.14f;
double pid = 3.14d;

La notación científica también funciona:

double avogadro = 6.022e23;
double tiny = 1.0e-9;

Conversión entre tipos numéricos

Java realiza una conversión de ampliación automáticamente cuando un tipo menor fluye hacia uno mayor (no se puede perder datos):

int x = 7;
double promoted = x;   // 7.0 — int widens to double automatically

Ir en sentido contrario es una conversión de reducción: el valor puede no caber, por lo que Java te obliga a escribir una conversión explícita y descarta silenciosamente lo que no cabe. Es truncamiento, no redondeo:

double d = 9.99;
int i = (int) d;       // 9 — the fraction is dropped, never rounded

long big = 9_000_000_000L;
int truncated = (int) big;   // 410065408 — high bits lost, value is garbage

Por ello, reduce solo cuando estés seguro de que el valor cabe. Para redondear un double al entero más cercano en lugar de truncarlo, usa Math.round (consulta Java Math).

Las conversiones también ocurren dentro de expresiones. La división entera descarta el resto, lo que sorprende a los principiantes:

System.out.println(7 / 2);     // 3   — both operands are int, so int division
System.out.println(7 / 2.0);   // 3.5 — one double operand promotes the whole expression

Para las reglas completas sobre las conversiones explícitas, consulta Java Type Casting.

Desbordamiento

La aritmética entera se desborda silenciosamente alrededor de los límites del tipo. No se lanza ninguna excepción:

int max = Integer.MAX_VALUE;
System.out.println(max + 1);   // -2147483648 (Integer.MIN_VALUE)

Para la aritmética con verificación de desbordamiento, usa la familia Math.exact:

Math.addExact(Integer.MAX_VALUE, 1);   // throws ArithmeticException
Math.multiplyExact(100_000, 100_000);  // throws too

Útil cuando la corrección importa más que el rendimiento — cálculos financieros, tamaños de asignación, etc.

Precisión de punto flotante

double y float son IEEE 754 binario — no pueden representar la mayoría de las fracciones decimales con exactitud:

System.out.println(0.1 + 0.2);   // 0.30000000000000004

Nunca compares valores de punto flotante con ==. Compara dentro de una tolerancia:

double diff = Math.abs(a - b);
if (diff < 1e-9) { /* close enough */ }

Para cantidades de dinero o en cualquier caso donde necesites aritmética decimal exacta, usa BigDecimal:

import java.math.BigDecimal;

BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum);   // 0.3

Pasa siempre cadenas a new BigDecimal(...). El constructor double reintroduciría la inexactitud binaria.

Valores especiales de punto flotante

double tiene tres valores que no son números ordinarios:

double posInf = Double.POSITIVE_INFINITY;
double negInf = Double.NEGATIVE_INFINITY;
double nan = Double.NaN;

System.out.println(1.0 / 0);          // Infinity
System.out.println(-1.0 / 0);         // -Infinity
System.out.println(0.0 / 0);          // NaN

System.out.println(nan == nan);       // false — NaN compares unequal to everything
System.out.println(Double.isNaN(nan)); // true

Usa Double.isNaN(x) para verificar NaN; == no funcionará.

Las clases envolventes

Cada primitivo tiene una clase envolvente correspondiente: Byte, Short, Integer, Long, Float, Double. Las envolventes extienden la clase abstracta Number. Las necesitas cuando:

  • Usas colecciones que contienen objetos: List<Integer>, Map<String, Double>.
  • Analizas desde cadenas: Integer.parseInt("42"), Double.parseDouble("3.14").
  • Conviertes a un tipo numérico diferente mediante .intValue(), .doubleValue(), etc.

Java autoboxea entre primitivo y envolvente automáticamente:

List<Integer> ids = new ArrayList<>();
ids.add(42);            // autobox: int → Integer
int first = ids.get(0); // unbox: Integer → int

BigInteger y BigDecimal

Cuando los números pueden ser mayores que long o necesitas precisión decimal:

import java.math.BigInteger;

BigInteger huge = new BigInteger("123456789012345678901234567890");
huge.multiply(huge);

BigDecimal price = new BigDecimal("19.95");
BigDecimal tax = price.multiply(new BigDecimal("0.07"));

Son más lentos que los primitivos, pero para los casos que los requieren, es la compensación correcta.

Una demostración

java— editable, runs on the server

Qué sigue

  • Java MathMath.abs, Math.round, Math.pow, y el resto del kit de herramientas numéricas.
  • Java Operators — cómo se comportan los operadores aritméticos, de comparación y a nivel de bits en estos tipos.
  • Java Booleans — el tipo de dos valores de Java, con mucho menos detalle.

Práctica

Práctica
¿Qué tipo es más apropiado para una cantidad de dinero en Java?
¿Qué tipo es más apropiado para una cantidad de dinero en Java?
Was this page helpful?