Sistemas de numeración: Binario, Hexadecimal, Decimal y Operaciones con bits
Este artículo es una introducción completa a los sistemas de numeración, incluyendo binario, hexadecimal, decimal, conversiones y operaciones con bits, todo con ejemplos prácticos.
Lo esencial
Las computadoras utilizan sistemas binarios (0 y 1). El hexadecimal actúa como representación compacta para valores binarios. Las operaciones con bits permiten manipulación directa de datos a nivel de bit.
Ruta de aprendizaje
Principiante (Pasos 1-3):
- Comprender los fundamentos de los sistemas de numeración (decimal, binario, hexadecimal)
- Practicar conversiones simples (decimal ↔ binario ↔ hexadecimal)
- Aprender operaciones básicas con bits (AND, OR, XOR)
Intermedio (Pasos 4-6): 4. Entender el complemento a dos y números negativos 5. Aplicaciones prácticas (direcciones IP, colores, direcciones MAC) 6. Operaciones de desplazamiento y manipulación de bits
Avanzado (Pasos 7-10): 7. Temas especializados (BCD, código Gray, CRC) 8. Formato de punto flotante IEEE 754 9. Endianness y orden de bytes en red 10. Optimización de rendimiento con operaciones de bits
💡 Consejo profesional: comienza con los ejercicios interactivos para poner a prueba tu comprensión.
Descripción técnica concisa
Los sistemas de numeración son métodos para representar números usando diferentes bases. Las computadoras utilizan internamente el sistema binario (base 2), mientras que los humanos preferimos el sistema decimal (base 10).
Sistemas de numeración importantes:
Sistema decimal (base 10)
- Dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- Valores posicionales: 10⁰, 10¹, 10², 10³, …
- Uso: comunicación humana, matemáticas cotidianas
- Ejemplo: 123 = 1×10² + 2×10¹ + 3×10⁰
Representación visual:
1 2 3
↓ ↓ ↓
10² 10¹ 10⁰
100 10 1
= 100 + 20 + 3 = 123
Sistema binario (base 2)
- Dígitos: 0, 1
- Valores posicionales: 2⁰, 2¹, 2², 2³, …
- Uso: representación interna en computadoras
- Ejemplo: 1011 = 1×2³ + 0×2² + 1×2¹ + 1×2⁰ = 11
⚠️ Importante: las computadoras trabajan internamente solo con 0 y 1. Todos los datos finalmente se almacenan como números binarios.
Representación visual:
1 0 1 1
↓ ↓ ↓ ↓
2³ 2² 2¹ 2⁰
8 4 2 1
= 8 + 0 + 2 + 1 = 11
Sistema hexadecimal (base 16)
- Dígitos: 0-9, A, B, C, D, E, F
- Valores posicionales: 16⁰, 16¹, 16², 16³, …
- Uso: representación binaria compacta, colores, direcciones de memoria
- Ejemplo: A3 = 10×16¹ + 3×16⁰ = 163
💡 Consejo profesional: 1 dígito hexadecimal = 4 dígitos binarios. El hexadecimal es perfecto para representar binario porque es más compacto y legible.
Representación visual:
A 3
↓ ↓
16¹ 16⁰
16 1
= 160 + 3 = 163
Sistema octal (base 8)
- Dígitos: 0, 1, 2, 3, 4, 5, 6, 7
- Valores posicionales: 8⁰, 8¹, 8², 8³, …
- Uso: históricamente usado en sistemas Unix
- Ejemplo: 75 = 7×8¹ + 5×8⁰ = 61
📜 Histórico: el octal fue ampliamente utilizado en los primeros sistemas Unix (por ejemplo, permisos de archivo con
chmod 755). Hoy en día el hexadecimal es más común.
Representación visual:
7 5
↓ ↓
8¹ 8⁰
8 1
= 56 + 5 = 61
Puntos clave para examen
- Sistema decimal: base 10, dígitos 0-9, valores posicionales 10ⁿ
- Sistema binario: base 2, dígitos 0-1, representación en computadoras
- Sistema hexadecimal: base 16, dígitos 0-9 y A-F, representación compacta
- Conversión: división/multiplicación por la base, método de valores posicionales
- Operaciones con bits: AND, OR, XOR, NOT, operaciones de desplazamiento
- Complemento a dos: números negativos en sistema binario
- Relevante para exámenes: base de arquitectura de computadoras y programación
Componentes principales
- Sistemas de numeración: decimal, binario, hexadecimal, octal
- Conversión: entre diferentes bases
- Operaciones con bits: AND, OR, XOR, NOT, desplazamiento
- Complemento a dos: números negativos
- Aritmética de computadora: suma, resta, multiplicación
- Tipos de datos: bits, bytes, palabras
- Representación de memoria: direcciones hexadecimales
- Detección de errores: paridad, sumas de comprobación
Conversiones paso a paso
💡 Consejo profesional: practica estas conversiones regularmente; son fundamentales para entender sistemas de computadoras. Además, aparecen en casi todos los exámenes de certificación técnica.
Nuestro calculador en línea gratuito:
Zahlensystem-Umrechnung
Decimal a binario (división entre 2)
Ejemplo: 13₁₀ → Binario
13 ÷ 2 = 6 resto 1 ← bit menos significativo
6 ÷ 2 = 3 resto 0
3 ÷ 2 = 1 resto 1
1 ÷ 2 = 0 resto 1 ← bit más significativo
Leer de abajo hacia arriba: 1101₂
Binario a decimal (método de valores posicionales)
Ejemplo: 1101₂ → Decimal
1 1 0 1
↓ ↓ ↓ ↓
2³ 2² 2¹ 2⁰
8 4 2 1
= 1×8 + 1×4 + 0×2 + 1×1
= 8 + 4 + 0 + 1
= 13₁₀
Decimal a hexadecimal (división entre 16)
Ejemplo: 255₁₀ → Hex
255 ÷ 16 = 15 resto 15 (F)
15 ÷ 16 = 0 resto 15 (F)
Leer de abajo hacia arriba: FF₁₆
Hexadecimal a binario (grupos de 4 bits)
Ejemplo: A3₁₆ → Binario
A (10) 3
↓ ↓
1010 0011
Combinado: 10100011₂
Binario a hexadecimal (grupos de 4 bits)
Ejemplo: 10100011₂ → Hex
1010 0011
↓ ↓
A 3
Combinado: A3₁₆
Ejemplos prácticos
1. Conversión entre sistemas de numeración
public class SistemasNumeracion {
// Decimal a binario
public static String decimalABinario(int decimal) {
if (decimal == 0) return "0";
StringBuilder binario = new StringBuilder();
while (decimal > 0) {
binario.append(decimal % 2);
decimal /= 2;
}
return binario.reverse().toString();
}
// Binario a decimal
public static int binarioADecimal(String binario) {
int decimal = 0;
int potencia = 0;
for (int i = binario.length() - 1; i >= 0; i--) {
if (binario.charAt(i) == '1') {
decimal += Math.pow(2, potencia);
}
potencia++;
}
return decimal;
}
// Decimal a hexadecimal
public static String decimalAHex(int decimal) {
if (decimal == 0) return "0";
char[] digitos = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
StringBuilder hex = new StringBuilder();
while (decimal > 0) {
int resto = decimal % 16;
hex.append(digitos[resto]);
decimal /= 16;
}
return hex.reverse().toString();
}
// Hexadecimal a decimal
public static int hexADecimal(String hex) {
int decimal = 0;
String digitos = "0123456789ABCDEF";
for (int i = 0; i < hex.length(); i++) {
char caracter = hex.charAt(i);
int valor = digitos.indexOf(caracter);
decimal = decimal * 16 + valor;
}
return decimal;
}
// Binario a hexadecimal
public static String binarioAHex(String binario) {
// Dividir binario en grupos de 4
while (binario.length() % 4 != 0) {
binario = "0" + binario;
}
StringBuilder hex = new StringBuilder();
for (int i = 0; i < binario.length(); i += 4) {
String grupo = binario.substring(i, i + 4);
int valor = binarioADecimal(grupo);
hex.append(decimalAHex(valor));
}
return hex.toString();
}
// Hexadecimal a binario
public static String hexABinario(String hex) {
String[] mapaHex = {
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
};
StringBuilder binario = new StringBuilder();
for (int i = 0; i < hex.length(); i++) {
char caracter = hex.charAt(i);
int valor = "0123456789ABCDEF".indexOf(caracter);
binario.append(mapaHex[valor]);
}
// Eliminar ceros iniciales
while (binario.length() > 1 && binario.charAt(0) == '0') {
binario.deleteCharAt(0);
}
return binario.toString();
}
public static void main(String[] args) {
int numero = 175;
System.out.println("Número: " + numero);
System.out.println("Binario: " + decimalABinario(numero));
System.out.println("Hexadecimal: " + decimalAHex(numero));
String binario = "10101111";
String hex = "AF";
System.out.println("\nBinario " + binario + " = Decimal " + binarioADecimal(binario));
System.out.println("Hexadecimal " + hex + " = Decimal " + hexADecimal(hex));
System.out.println("Binario " + binario + " = Hexadecimal " + binarioAHex(binario));
System.out.println("Hexadecimal " + hex + " = Binario " + hexABinario(hex));
}
}
2. Operaciones con bits en diferentes lenguajes
// Java - Operaciones con bits
public class BitOperaciones {
public static void main(String[] args) {
int a = 12; // 1100 en binario
int b = 10; // 1010 en binario
System.out.println("a = " + a + " (Binario: " + Integer.toBinaryString(a) + ")");
System.out.println("b = " + b + " (Binario: " + Integer.toBinaryString(b) + ")");
// AND bit a bit (&)
int and = a & b; // 1100 & 1010 = 1000 (8)
System.out.println("a & b = " + and + " (Binario: " + Integer.toBinaryString(and) + ")");
// OR bit a bit (|)
int or = a | b; // 1100 | 1010 = 1110 (14)
System.out.println("a | b = " + or + " (Binario: " + Integer.toBinaryString(or) + ")");
// XOR bit a bit (^)
int xor = a ^ b; // 1100 ^ 1010 = 0110 (6)
System.out.println("a ^ b = " + xor + " (Binario: " + Integer.toBinaryString(xor) + ")");
// NOT bit a bit (~)
int notA = ~a; // ~1100 = 0011 (con complemento a dos)
System.out.println("~a = " + notA + " (Binario: " + Integer.toBinaryString(notA) + ")");
// Desplazamiento a la izquierda (<<)
int leftShift = a << 2; // 1100 << 2 = 110000 (48)
System.out.println("a << 2 = " + leftShift + " (Binario: " + Integer.toBinaryString(leftShift) + ")");
// Desplazamiento a la derecha (>>)
int rightShift = a >> 1; // 1100 >> 1 = 0110 (6)
System.out.println("a >> 1 = " + rightShift + " (Binario: " + Integer.toBinaryString(rightShift) + ")");
// Desplazamiento a la derecha sin signo (>>>)
int unsignedRightShift = a >>> 1; // 1100 >>> 1 = 0110 (6)
System.out.println("a >>> 1 = " + unsignedRightShift + " (Binario: " + Integer.toBinaryString(unsignedRightShift) + ")");
// Aplicaciones prácticas
aplicacionesPracticas();
}
private static void aplicacionesPracticas() {
System.out.println("\n=== Aplicaciones Prácticas ===");
// Verificar si un bit está establecido (¿está el 3er bit activado?)
int numero = 12; // 1100
int posicionBit = 2;
boolean bitActivado = (numero & (1 << posicionBit)) != 0;
System.out.println("Bit " + posicionBit + " en " + numero + " activado: " + bitActivado);
// Establecer un bit
int conBit = numero | (1 << posicionBit);
System.out.println("Activar bit " + posicionBit + ": " + conBit);
// Limpiar un bit
int sinBit = numero & ~(1 << posicionBit);
System.out.println("Desactivar bit " + posicionBit + ": " + sinBit);
// Cambiar un bit (toggle)
int intercambiado = numero ^ (1 << posicionBit);
System.out.println("Cambiar bit " + posicionBit + ": " + intercambiado);
// Extraer componentes RGB de un color
int color = 0xFF6B35; // Naranja
int rojo = (color >> 16) & 0xFF;
int verde = (color >> 8) & 0xFF;
int azul = color & 0xFF;
System.out.println("\nColor: #" + Integer.toHexString(color).toUpperCase());
System.out.println("Rojo: " + rojo);
System.out.println("Verde: " + verde);
System.out.println("Azul: " + azul);
}
}
3. Complemento a dos para números negativos
⚠️ Importante: El complemento a dos es el estándar para representar números negativos en computadores modernos. Evita el complemento a uno y la notación de magnitud con signo.
public class ComplementoADos {
// Calcular complemento a dos
public static String complementoADos(int numero, int bits) {
if (numero >= 0) {
return String.format("%" + bits + "s", Integer.toBinaryString(numero)).replace(' ', '0');
}
// Número negativo: 2^bits + numero
int positivo = (int) (Math.pow(2, bits) + numero);
return String.format("%" + bits + "s", Integer.toBinaryString(positivo)).replace(' ', '0');
}
// Convertir desde complemento a dos a valor decimal
public static int desdeComplementoADos(String binario) {
int bits = binario.length();
// Si el bit más alto es 0, es un número positivo
if (binario.charAt(0) == '0') {
return Integer.parseInt(binario, 2);
}
// Número negativo: - (2^bits - valor)
int valor = Integer.parseInt(binario, 2);
return valor - (int) Math.pow(2, bits);
}
public static void main(String[] args) {
int[] numeros = {13, 5, 0, -1, -5, -13};
int bits = 8;
System.out.println("Complemento a dos con " + bits + " bits:");
System.out.println("Número\tBinario\t\tDecimal");
System.out.println("------\t------\t\t-------");
for (int numero : numeros) {
String binario = complementoADos(numero, bits);
System.out.println(numero + "\t" + binario + "\t" + desdeComplementoADos(binario));
}
// Mostrar el rango
System.out.println("\nRango con " + bits + " bits:");
System.out.println("Mínimo: " + (-(int) Math.pow(2, bits-1)));
System.out.println("Máximo: " + ((int) Math.pow(2, bits-1) - 1));
// Demostrar desbordamiento
System.out.println("\nDemostración de desbordamiento:");
int maximo = (int) Math.pow(2, bits-1) - 1;
int desbordamiento = maximo + 1;
System.out.println("Máx: " + maximo + " -> " + complementoADos(maximo, bits));
System.out.println("Máx+1: " + desbordamiento + " -> " + complementoADos(desbordamiento, bits));
System.out.println("Esperado: " + (-(int) Math.pow(2, bits-1)) + " -> " + complementoADos(-(int) Math.pow(2, bits-1), bits));
}
}
4. Aritmética computacional
⚠️ Advertencia: La aritmética binaria puede provocar desbordamientos. Siempre verifica los límites de rango de tus tipos de datos.
public class ArithmeticaComputacional {
// Suma binaria
public static String sumaBinaria(String a, String b) {
int longitud = Math.max(a.length(), b.length());
// Rellenar con ceros a la izquierda
a = String.format("%" + longitud + "s", a).replace(' ', '0');
b = String.format("%" + longitud + "s", b).replace(' ', '0');
StringBuilder resultado = new StringBuilder();
int acarreo = 0;
// Sumar de derecha a izquierda
for (int i = longitud - 1; i >= 0; i--) {
int suma = acarreo + (a.charAt(i) - '0') + (b.charAt(i) - '0');
resultado.append(suma % 2);
acarreo = suma / 2;
}
// Agregar acarreo final
if (acarreo > 0) {
resultado.append(acarreo);
}
return resultado.reverse().toString();
}
// Resta binaria (método del complemento a dos)
public static String restaBinaria(String a, String b) {
// Negar b (complemento a dos)
String negado = complementoADosNegar(b);
// a + (-b)
return sumaBinaria(a, negado);
}
private static String complementoADosNegar(String binario) {
// Invertir bits
StringBuilder invertido = new StringBuilder();
for (char bit : binario.toCharArray()) {
invertido.append(bit == '0' ? '1' : '0');
}
// Sumar 1
return sumaBinaria(invertido.toString(), "1");
}
// Multiplicación binaria
public static String multiplicacionBinaria(String a, String b) {
int aDecimal = Integer.parseInt(a, 2);
int bDecimal = Integer.parseInt(b, 2);
int producto = aDecimal * bDecimal;
return Integer.toBinaryString(producto);
}
// Aritmética de punto fijo
public static double puntofijosuma(double a, double b, int decimales) {
int factor = (int) Math.pow(10, decimales);
int aInt = (int) Math.round(a * factor);
int bInt = (int) Math.round(b * factor);
int resultadoInt = aInt + bInt;
return (double) resultadoInt / factor;
}
// Representación de punto flotante (simplificada)
public static void puntoflocanteRepresentacion(double numero) {
if (numero == 0) {
System.out.println("0 = 0.0 × 2^0");
return;
}
boolean negativo = numero < 0;
numero = Math.abs(numero);
int exponente = 0;
// Normalizar
while (numero >= 2.0) {
numero /= 2.0;
exponente++;
}
while (numero < 1.0) {
numero *= 2.0;
exponente--;
}
System.out.println((negativo ? "-" : "") + numero + " × 2^" + exponente);
}
public static void main(String[] args) {
System.out.println("=== Aritmética Binaria ===");
String a = "1011"; // 11
String b = "1101"; // 13
System.out.println("a = " + a + " (" + Integer.parseInt(a, 2) + ")");
System.out.println("b = " + b + " (" + Integer.parseInt(b, 2) + ")");
String suma = sumaBinaria(a, b);
System.out.println("a + b = " + suma + " (" + Integer.parseInt(suma, 2) + ")");
String diferencia = restaBinaria(b, a);
System.out.println("b - a = " + diferencia + " (" + Integer.parseInt(diferencia, 2) + ")");
String producto = multiplicacionBinaria(a, b);
System.out.println("a × b = " + producto + " (" + Integer.parseInt(producto, 2) + ")");
System.out.println("\n=== Aritmética de Punto Fijo ===");
double x = 12.34;
double y = 5.67;
double sumaFP = puntofijosuma(x, y, 2);
System.out.println(x + " + " + y + " = " + sumaFP + " (2 decimales)");
System.out.println("\n=== Representación de Punto Flotante ===");
double[] numeros = {12.5, 0.75, -3.125, 256.0};
for (double numero : numeros) {
System.out.print(numero + " = ");
puntoflocanteRepresentacion(numero);
}
}
}
5. Operaciones de bits en Python y sistemas numéricos
# Sistemas numéricos y operaciones de bits en Python
def decimal_a_binario(decimal):
"""Convertir decimal a binario"""
if decimal == 0:
return "0"
binario = ""
while decimal > 0:
binario = str(decimal % 2) + binario
decimal //= 2
return binario
def binario_a_decimal(binario):
"""Convertir binario a decimal"""
return int(binario, 2)
def decimal_a_hex(decimal):
"""Convertir decimal a hexadecimal"""
digitos_hex = "0123456789ABCDEF"
if decimal == 0:
return "0"
hex_resultado = ""
while decimal > 0:
hex_resultado = digitos_hex[decimal % 16] + hex_resultado
decimal //= 16
return hex_resultado
def hex_a_decimal(hexadecimal):
"""Convertir hexadecimal a decimal"""
return int(hexadecimal, 16)
def demo_operaciones_bits():
"""Demostración de operaciones de bits"""
a = 12 # 1100
b = 10 # 1010
print(f"a = {a} (Binario: {bin(a)})")
print(f"b = {b} (Binario: {bin(b)})")
# AND bit a bit
resultado_and = a & b
print(f"a & b = {resultado_and} (Binario: {bin(resultado_and)})")
# OR bit a bit
resultado_or = a | b
print(f"a | b = {resultado_or} (Binario: {bin(resultado_or)})")
# XOR bit a bit
resultado_xor = a ^ b
print(f"a ^ b = {resultado_xor} (Binario: {bin(resultado_xor)})")
# NOT bit a bit
no_a = ~a
print(f"~a = {no_a} (Binario: {bin(no_a & 0xFFFFFFFF)})")
# Desplazamiento a la izquierda
desplazamiento_izq = a << 2
print(f"a << 2 = {desplazamiento_izq} (Binario: {bin(desplazamiento_izq)})")
# Desplazamiento a la derecha
desplazamiento_der = a >> 1
print(f"a >> 1 = {desplazamiento_der} (Binario: {bin(desplazamiento_der)})")
def color_de_rgb(rojo, verde, azul):
"""Combinar RGB como valor de 24 bits"""
return (rojo << 16) | (verde << 8) | azul
def rgb_de_color(color):
"""Extraer componentes RGB de un color de 24 bits"""
rojo = (color >> 16) & 0xFF
verde = (color >> 8) & 0xFF
azul = color & 0xFF
return rojo, verde, azul
def demo_manipulacion_bits():
"""Demostración de manipulación de bits"""
numero = 0b10101000 # 168
print(f"Número original: {numero} (Binario: {bin(numero)})")
# Verificar bit
posicion_bit = 3
bit_establecido = (numero & (1 << posicion_bit)) != 0
print(f"Bit {posicion_bit} establecido: {bit_establecido}")
# Establecer bit
con_bit = numero | (1 << posicion_bit)
print(f"Establecer bit {posicion_bit}: {con_bit} (Binario: {bin(con_bit)})")
# Limpiar bit
sin_bit = numero & ~(1 << posicion_bit)
print(f"Limpiar bit {posicion_bit}: {sin_bit} (Binario: {bin(sin_bit)})")
# Alternar bit
alternado = numero ^ (1 << posicion_bit)
print(f"Alternar bit {posicion_bit}: {alternado} (Binario: {bin(alternado)})")
def programa_principal():
"""Programa principal con todas las demostraciones"""
print("=== Conversión de sistemas numéricos ===")
numero = 175
print(f"Decimal {numero}:")
print(f" Binario: {decimal_a_binario(numero)}")
print(f" Hex: {decimal_a_hex(numero)}")
print("\n=== Operaciones de bits ===")
demo_operaciones_bits()
print("\n=== Manipulación de bits ===")
demo_manipulacion_bits()
print("\n=== Colores como RGB ===")
naranja = color_de_rgb(255, 107, 53)
print(f"Naranja: #{naranja:06X}")
r, g, b = rgb_de_color(naranja)
print(f"RGB: ({r}, {g}, {b})")
print("\n=== Complemento a dos (8 bits) ===")
for i in range(-5, 6):
if i >= 0:
binario = format(i, '08b')
else:
binario = format((256 + i), '08b')
print(f"{i:3d}: {binario}")
if __name__ == "__main__":
programa_principal()
Ejemplos de aplicaciones reales
1. Direcciones IP (IPv4)
Las direcciones IPv4 constan de 4 bytes (32 bits), típicamente expresadas en notación decimal:
Ejemplo: 192.168.1.1
192 168 1 1
↓ ↓ ↓ ↓
11000000 10101000 00000001 00000001
C0 A8 01 01 (Hex)
Binario: 11000000101010000000000100000001
Hex: C0A80101
Ejemplo de máscara de subred: 255.255.255.0
255 255 255 0
↓ ↓ ↓ ↓
11111111 11111111 11111111 00000000
FF FF FF 00 (Hex)
2. Direcciones MAC
Las direcciones MAC tienen 6 bytes (48 bits), típicamente expresadas en notación hexadecimal:
Ejemplo: 00:1A:2B:3C:4D:5E
00:1A:2B:3C:4D:5E
↓ ↓ ↓ ↓ ↓ ↓
00000000:00011010:00101011:00111100:01001101:01011110
Fabricante (OUI): 00:1A:2B
ID del dispositivo: 3C:4D:5E
3. Unicode y UTF-8
Los caracteres Unicode se representan como puntos de código, UTF-8 codifica estos en bytes:
Ejemplo: ‘A’ (U+0041)
Unicode: U+0041
Decimal: 65
Binario: 01000001
UTF-8: 01000001 (1 byte)
Ejemplo: ’€’ (U+20AC)
Unicode: U+20AC
Decimal: 8364
Binario: 00100000 10101100
UTF-8: 11100010 10000011 10101100 (3 bytes)
Hex: E2 82 AC
4. Códigos de color (RGB)
Los colores web se representan como valores hexadecimales de 24 bits:
Ejemplo: #FF6B35 (Naranja)
#FF6B35
↓↓↓↓↓↓
Rojo Verde Azul
FF 6B 35
↓ ↓ ↓
255 107 53
Binario: 11111111 01101011 00110101
Ejemplo en Java:
int naranja = 0xFF6B35;
int rojo = (naranja >> 16) & 0xFF; // 255
int verde = (naranja >> 8) & 0xFF; // 107
int azul = naranja & 0xFF; // 53
5. Tamaños de archivo (binario vs. decimal)
Prefijos binarios (IEC 80000-13):
1 KiB = 2¹⁰ = 1,024 bytes
1 MiB = 2²⁰ = 1,048,576 bytes
1 GiB = 2³⁰ = 1,073,741,824 bytes
Prefijos decimales (SI):
1 KB = 10³ = 1,000 bytes
1 MB = 10⁶ = 1,000,000 bytes
1 GB = 10⁹ = 1,000,000,000 bytes
Ejemplo: 1 GB de disco duro
Fabricante (decimal): 1,000,000,000 bytes
Sistema operativo (binario): 1,000,000,000 ÷ 1,073,741,824 = 0.93 GB
6. Tabla ASCII (fragmento)
| Carácter | Decimal | Hex | Binario |
|---|---|---|---|
| A | 65 | 41 | 01000001 |
| B | 66 | 42 | 01000010 |
| C | 67 | 43 | 01000011 |
| a | 97 | 61 | 01100001 |
| b | 98 | 62 | 01100010 |
| c | 99 | 63 | 01100011 |
| 0 | 48 | 30 | 00110000 |
| 9 | 57 | 39 | 00111001 |
Ejercicios interactivos
Tareas de conversión
Ejercicio 1: Decimal a binario Convierte los siguientes números decimales a binario:
- 42
- 127
- 255
Ver soluciones
42₁₀ = 101010₂
127₁₀ = 1111111₂
255₁₀ = 11111111₂Ejercicio 2: Binario a decimal Convierte los siguientes números binarios a decimal:
- 10101
- 11110000
- 10000000
Ver soluciones
10101₂ = 21₁₀
11110000₂ = 240₁₀
10000000₂ = 128₁₀Ejercicio 3: Decimal a hexadecimal Convierte los siguientes números decimales a hexadecimal:
- 100
- 255
- 4095
Ver soluciones
100₁₀ = 64₁₆
255₁₀ = FF₁₆
4095₁₀ = FFF₁₆Ejercicio 4: Hexadecimal a binario Convierte los siguientes números hexadecimales a binario:
- A5
- FF
- 1B
Ver soluciones
A5₁₆ = 10100101₂
FF₁₆ = 11111111₂
1B₁₆ = 00011011₂Cuestionario de operaciones de bits
Pregunta 1: ¿Cuál es el resultado de 12 & 10?
Ver solución
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 & 1010 = 1000₂ = 8₁₀Pregunta 2: ¿Cuál es el resultado de 12 | 10?
Ver solución
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 | 1010 = 1110₂ = 14₁₀Pregunta 3: ¿Cuál es el resultado de 12 ^ 10?
Ver solución
12₁₀ = 1100₂
10₁₀ = 1010₂
1100 ^ 1010 = 0110₂ = 6₁₀Pregunta 4: ¿Cuál es el resultado de 8 << 2?
Ver solución
8₁₀ = 1000₂
1000 << 2 = 100000₂ = 32₁₀Pregunta 5: ¿Cuál es el resultado de 16 >> 2?
Ver solución
16₁₀ = 10000₂
10000 >> 2 = 100₂ = 4₁₀Tareas de Desafío
Tarea 6: Manipulación de Bits Dada la número 42 (101010₂). Establece el 3.er bit (desde la derecha, indexado desde 0).
Mostrar solución
42 = 101010₂
3.er bit desde la derecha = posición de bit 2
42 | (1 << 2) = 42 | 4 = 46₁₀ = 101110₂Tarea 7: Complemento a Dos Representa -5 en complemento a dos de 8 bits.
Mostrar solución
5₁₀ = 00000101₂
Invertir: 11111010₂
+ 1: 11111011₂
-5₁₀ = 11111011₂ (complemento a dos de 8 bits)Tarea 8: Dirección IP Convierte la dirección IP 10.0.0.1 a hexadecimal.
Mostrar solución
10.0.0.1
↓ ↓ ↓ ↓
0A 00 00 01
Hex: 0A000001Errores Comunes y Trampas
1. Errores de Límite en Posiciones de Bits
Problema: Las posiciones de bits se cuentan frecuentemente de forma incorrecta (indexado desde 0 vs. indexado desde 1)
// ❌ Incorrecto: La posición de bit 3 es el 4.o bit desde la derecha
int bitPosition = 3;
boolean bitSet = (zahl & (1 << bitPosition)) != 0; // Verifica bit 3 (4.o bit)
// ✅ Correcto: Documentación clara de la indexación
// Posición de bit 0 = bit más a la derecha (LSB)
// Posición de bit 7 = bit más a la izquierda en 8 bits
int bitPosition = 2; // 3.er bit desde la derecha (indexado desde 0)
boolean bitSet = (zahl & (1 << bitPosition)) != 0;
2. Tratamiento de Signos en Desplazamientos
Problema: El desplazamiento a la derecha se comporta diferente para valores con y sin signo
// Java: Desplazamiento a la derecha con signo (>>) rellena con el bit de signo
int x = -8; // 11111111111111111111111111111000
int result = x >> 2; // 11111111111111111111111111111110 (-2)
// Desplazamiento a la derecha sin signo (>>>) rellena con ceros
int x = -8;
int result = x >>> 2; // 00111111111111111111111111111110 (1073741822)
3. Problemas de Desbordamiento
Problema: El desbordamiento de enteros se ignora frecuentemente
// ❌ Sin verificación de desbordamiento
int max = Integer.MAX_VALUE; // 2147483647
int overflow = max + 1; // -2147483648 (¡desbordamiento!)
// ✅ Con verificación de desbordamiento
if (max == Integer.MAX_VALUE) {
throw new ArithmeticException("Integer overflow");
}
4. Malos Entendidos sobre Convenciones Hexadecimales
Problema: Diferentes formas de escribir números hexadecimales
// Diferentes convenciones:
0xFF // Prefijo Java/C
0xFF // Prefijo C#
0xFF // Prefijo JavaScript
#FF // CSS/Web
FFh // Ensamblador
$FF // Pascal
5. Olvidar Endianness
Problema: Se ignora el orden de bytes
// Little Endian (x86, ARM): byte menos significativo primero
int valor = 0x12345678;
// En memoria: 78 56 34 12
// Big Endian (Network, PowerPC): byte más significativo primero
// En memoria: 12 34 56 78
// Conversión:
int littleEndian = 0x12345678;
int bigEndian = Integer.reverseBytes(littleEndian); // 0x78563412
6. Base Incorrecta en parseInt
Problema: La base no se especifica correctamente
// ❌ Incorrecto: Decimal en lugar de binario
int valor = Integer.parseInt("1010"); // 1010 (decimal)
// ✅ Correcto: Especificar la base
int valor = Integer.parseInt("1010", 2); // 10 (decimal)
int valorHex = Integer.parseInt("FF", 16); // 255 (decimal)
7. Exceder el Rango de Complemento a Dos
Problema: El número no cabe en el ancho de bit especificado
// Complemento a dos de 8 bits: -128 a 127
int valor = 200; // ❌ ¡Excede el rango!
// Verificación de rango:
if (valor < -128 || valor > 127) {
throw new IllegalArgumentException("Valor fuera del rango de 8 bits");
}
8. División de Float vs. Entero
Problema: La división de enteros trunca los decimales
// ❌ Incorrecto: División de enteros
int resultado = 5 / 2; // 2 (en lugar de 2.5)
// ✅ Correcto: División de floats
double resultado = 5.0 / 2.0; // 2.5
9. Negación vs. Complemento
Problema: Confusión entre negación lógica y complemento de bits
// NOT lógico (!)
boolean a = true;
boolean b = !a; // false
// NOT de bits (~)
int x = 5; // 0101
int y = ~x; // 1010 (con complemento a dos: -6)
10. Ceros Iniciales en Hexadecimal
Problema: Los ceros iniciales cambian el significado en ciertos contextos
// En Java: 0x0F = 15, 0xF = 15 (iguales)
// Pero en comparaciones de strings:
String a = "0F";
String b = "F";
// a.equals(b) = false!
Consejos Prácticos para Desarrolladores
1. Depuración con Vista Binaria/Hexadecimal
Usar herramientas del IDE:
// IntelliJ/Eclipse: Vista binaria en el depurador
// Variable: 175
// Binaria: 10101111
// Hex: AF
Logging con diferentes bases:
System.out.println("Decimal: " + zahl);
System.out.println("Binaria: " + Integer.toBinaryString(zahl));
System.out.println("Hex: " + Integer.toHexString(zahl));
System.out.println("Octal: " + Integer.toOctalString(zahl));
2. Flags de Bits en APIs
Flags de estado eficientes:
// Definir constantes de flags
public static final int READ = 1 << 0; // 0001
public static final int WRITE = 1 << 1; // 0010
public static final int EXECUTE = 1 << 2; // 0100
// Combinar flags
int permissions = READ | WRITE; // 0011
// Verificar flags
boolean canRead = (permissions & READ) != 0;
boolean canWrite = (permissions & WRITE) != 0;
boolean canExecute = (permissions & EXECUTE) != 0;
3. Ventajas de Rendimiento de Operaciones de Bits
Multiplicación/División mediante desplazamientos:
// Más rápido que * 2
int x = 5;
int duplicado = x << 1; // 10
// Más rápido que / 2
int mitad = x >> 1; // 2
// Módulo 2^n con AND
int modulo8 = x & 0x7; // x % 8
⚠️ Precaución: Los compiladores modernos a menudo optimizan automáticamente, úsalo solo en escenarios de rendimiento críticos.
4. Manipular Valores de Color
Procesar colores RGB eficientemente:
// Crear color
int color = (255 << 16) | (107 << 8) | 53; // #FF6B35
// Extraer componentes
int rojo = (color >> 16) & 0xFF;
int verde = (color >> 8) & 0xFF;
int azul = color & 0xFF;
// Manipular color
int nuevoColor = color & 0x00FFFFFF; // Borrar componente roja
nuevoColor |= (200 << 16); // Establecer nuevo valor rojo
5. Byte Order de Red
Garantizar portabilidad:
// Host to Network Short (16 bits)
short puertoHost = 8080;
short puertoRed = Short.reverseBytes(puertoHost);
// Network to Host Long (32 bits)
int direccionRed = 0xC0A80101; // 192.168.1.1
int direccionHost = Integer.reverseBytes(direccionRed);
6. Máscaras de Bits para Configuración
Almacenar configuración de forma compacta:
public class Config {
private int flags = 0;
public static final int DEBUG = 1 << 0;
public static final int VERBOSE = 1 << 1;
public static final int LOGGING = 1 << 2;
public void setFlag(int flag) {
flags |= flag;
}
public void clearFlag(int flag) {
flags &= ~flag;
}
public boolean hasFlag(int flag) {
return (flags & flag) != 0;
}
}
7. Estructuras de Datos Eficientes en Memoria
Bits para valores booleanos:
// En lugar de 8 booleans (8 bytes):
// boolean[] flags = new boolean[8];
// Un int (4 bytes) para 8 flags:
int flags = 0;
flags |= (1 << 3); // Establecer 3.er flag
8. Funciones Hash con Operaciones de Bits
Función hash simple:
public static int simpleHash(String s) {
int hash = 0;
for (int i = 0; i < s.length(); i++) {
hash = (hash << 5) - hash + s.charAt(i);
}
return hash;
}
9. Cálculo de paridad
Bit de paridad para detección de errores:
public static boolean calculateParity(int x) {
boolean parity = false;
while (x != 0) {
parity = !parity;
x = x & (x - 1); // Elimina el bit establecido de menor valor
}
return parity;
}
10. Verificación de potencia de 2
Verificación eficiente de si un número es potencia de dos:
public static boolean isPowerOfTwo(int x) {
return x > 0 && (x & (x - 1)) == 0;
}
// Ejemplos:
// isPowerOfTwo(1) = true (2⁰)
// isPowerOfTwo(2) = true (2¹)
// isPowerOfTwo(4) = true (2²)
// isPowerOfTwo(8) = true (2³)
// isPowerOfTwo(6) = false
Temas avanzados
1. BCD (Decimal Codificado en Binario)
BCD codifica cada dígito decimal en 4 bits:
Ejemplo: 42 en BCD
4 2
↓ ↓
0100 0010
BCD: 01000010
Ventajas:
- Conversión simple hacia y desde decimal
- Aritmética decimal precisa
Desventajas:
- Uso ineficiente de memoria (6 de 16 valores sin usar)
- Aritmética más compleja
Implementación en Java:
public class BCD {
public static int decimalToBCD(int decimal) {
int bcd = 0;
int shift = 0;
while (decimal > 0) {
int digit = decimal % 10;
bcd |= (digit << shift);
decimal /= 10;
shift += 4;
}
return bcd;
}
public static int bcdToDecimal(int bcd) {
int decimal = 0;
int multiplier = 1;
while (bcd > 0) {
int digit = bcd & 0xF;
decimal += digit * multiplier;
bcd >>= 4;
multiplier *= 10;
}
return decimal;
}
}
2. Código Gray
El código Gray es un sistema numérico binario donde valores consecutivos difieren en un solo bit:
Tabla de código Gray (4 bits):
Decimal | Binario | Código Gray
--------|---------|-------------
0 | 0000 | 0000
1 | 0001 | 0001
2 | 0010 | 0011
3 | 0011 | 0010
4 | 0100 | 0110
5 | 0101 | 0111
6 | 0110 | 0101
7 | 0111 | 0100
Binario a código Gray:
public static int binaryToGray(int binary) {
return binary ^ (binary >> 1);
}
Código Gray a binario:
public static int grayToBinary(int gray) {
int binary = gray;
while (gray > 0) {
gray >>= 1;
binary ^= gray;
}
return binary;
}
Aplicación: Codificadores rotativos, minimización de errores en conmutadores
3. CRC (Comprobación de Redundancia Cíclica)
CRC es un método de detección de errores para transmisión de datos:
Implementación simple de CRC-8:
public class CRC8 {
private static final int POLYNOMIAL = 0x07;
public static int calculate(byte[] data) {
int crc = 0x00;
for (byte b : data) {
crc ^= b;
for (int i = 0; i < 8; i++) {
if ((crc & 0x80) != 0) {
crc = (crc << 1) ^ POLYNOMIAL;
} else {
crc <<= 1;
}
}
}
return crc & 0xFF;
}
}
Usos:
- Protocolos de red (Ethernet, USB)
- Verificación de integridad de archivos
- Detección de errores en memoria
4. Formato de punto flotante IEEE 754
Estándar para números en punto flotante:
Precisión simple de 32 bits:
Bit 31: Signo (S)
Bits 30-23: Exponente (E, 8 bits)
Bits 22-0: Mantisa (M, 23 bits)
Valor = (-1)^S × 2^(E-127) × (1 + M)
Ejemplo: 12.5 en IEEE 754
12.5 = 1100.1₂ = 1.1001₂ × 2³
S = 0 (positivo)
E = 127 + 3 = 130 = 10000010₂
M = 10010000000000000000000
IEEE 754: 01000001010010000000000000000000
Hex: 41480000
Implementación en Java:
public class IEEE754 {
public static String floatToBits(float value) {
int bits = Float.floatToIntBits(value);
return String.format("%32s", Integer.toBinaryString(bits))
.replace(' ', '0');
}
public static float bitsToFloat(String bits) {
int intValue = Integer.parseInt(bits, 2);
return Float.intBitsToFloat(intValue);
}
}
5. Endianness (Orden de bytes)
Big Endian: Byte más significativo primero (Network Byte Order) Little Endian: Byte menos significativo primero (x86, ARM)
Ejemplo: 0x12345678
Big Endian: 12 34 56 78
Little Endian: 78 56 34 12
Conversión en Java:
public class Endianness {
// Little Endian a Big Endian
public static int littleToBig(int value) {
return Integer.reverseBytes(value);
}
// Big Endian a Little Endian
public static int bigToLittle(int value) {
return Integer.reverseBytes(value);
}
// Verificar la endianness del sistema
public static boolean isLittleEndian() {
int test = 0x12345678;
byte[] bytes = new byte[] {
(byte) (test >> 24),
(byte) (test >> 16),
(byte) (test >> 8),
(byte) test
};
return bytes[0] == 0x78; // Little Endian
}
}
Importante en:
- Protocolos de red (TCP/IP utiliza Big Endian)
- Formatos de archivo
- Desarrollo multiplataforma
6. Bit de paridad
Método simple de detección de errores:
Paridad par:
Datos: 1011
Paridad: 0 (para que la cantidad de 1s sea par: 10110 → 3 unos = impar ❌)
Paridad: 1 (para que la cantidad de 1s sea par: 10111 → 4 unos = par ✅)
Implementación en Java:
public class Parity {
public static boolean calculateEvenParity(byte data) {
int count = Integer.bitCount(data & 0xFF);
return (count % 2) == 0;
}
public static byte setEvenParity(byte data) {
if (calculateEvenParity(data)) {
return (byte) (data & 0x7F); // Bit de paridad = 0
} else {
return (byte) (data | 0x80); // Bit de paridad = 1
}
}
}
7. Sumas de verificación
Sumas de verificación simples para integridad de datos:
Suma de verificación simple:
public class Checksum {
public static int calculate(byte[] data) {
int sum = 0;
for (byte b : data) {
sum += (b & 0xFF);
}
return sum & 0xFFFF; // Suma de verificación de 16 bits
}
public static boolean verify(byte[] data, int checksum) {
return calculate(data) == checksum;
}
}
8. Codificación Base64
Codificar datos binarios en caracteres ASCII:
Ejemplo:
Binario: 01000001 01000010 01000011 (ABC)
Base64: QUJD
Implementación en Java:
import java.util.Base64;
public class Base64Example {
public static String encode(String input) {
return Base64.getEncoder().encodeToString(input.getBytes());
}
public static String decode(String encoded) {
byte[] decoded = Base64.getDecoder().decode(encoded);
return new String(decoded);
}
}
9. Rotación de bits
Rotación sin pérdida de bits:
Rotación a la izquierda:
public static int rotateLeft(int value, int shift) {
return (value << shift) | (value >>> (32 - shift));
}
Rotación a la derecha:
public static int rotateRight(int value, int shift) {
return (value >>> shift) | (value << (32 - shift));
}
Ejemplo:
int x = 0b11000000; // 192
int rotated = rotateLeft(x, 2); // 0b00000011 (3)
10. Distancia de Hamming
Número de bits diferentes entre dos valores:
public static int hammingDistance(int a, int b) {
int xor = a ^ b;
return Integer.bitCount(xor);
}
// Ejemplo:
// hammingDistance(0b1010, 0b1100) = 2
// 1010 ^ 1100 = 0110 (2 unos)
Aplicación: Códigos de corrección de errores, criptografía
Tabla de conversión
| Decimal | Binario | Hexadecimal | Octal |
|---|---|---|---|
| 0 | 0000 | 0 | 0 |
| 1 | 0001 | 1 | 1 |
| 2 | 0010 | 2 | 2 |
| 3 | 0011 | 3 | 3 |
| 4 | 0100 | 4 | 4 |
| 5 | 0101 | 5 | 5 |
| 6 | 0110 | 6 | 6 |
| 7 | 0111 | 7 | 7 |
| 8 | 1000 | 8 | 10 |
| 9 | 1001 | 9 | 11 |
| 10 | 1010 | A | 12 |
| 11 | 1011 | B | 13 |
| 12 | 1100 | C | 14 |
| 13 | 1101 | D | 15 |
| 14 | 1110 | E | 16 |
| 15 | 1111 | F | 17 |
Resumen de operaciones con bits
Bit-Operationen
| Operador | Símbolo | Descripción | Ejemplo |
|----------|---------|-------------|----------|
| AND | & | AND bit a bit | 5 & 3 = 1 |
| OR | \| | OR bit a bit | `5 \| 3 = 7` |
| XOR | ^ | OR exclusivo | `5 ^ 3 = 6` |
| NOT | ~ | NOT bit a bit | `~5 = -6` |
| Left Shift | << | Desplazamiento a la izquierda | `5 << 2 = 20` |
| Right Shift | >> | Desplazamiento a la derecha | `5 >> 1 = 2` |
| Unsigned Right Shift | >>> | Desplazamiento a la derecha sin signo | `5 >>> 1 = 2` |
Tamaños de memoria
| Unidad | Bytes | Bits | Rango (sin signo) |
|---|---|---|---|
| Byte | 1 | 8 | 0 - 255 |
| Word | 2 | 16 | 0 - 65,535 |
| DWord | 4 | 32 | 0 - 4,294,967,295 |
| QWord | 8 | 64 | 0 - 18,446,744,073,709,551,615 |
Rango del complemento a dos
| Bits | Mínimo | Máximo |
|---|---|---|
| 8 | -128 | 127 |
| 16 | -32,768 | 32,767 |
| 32 | -2,147,483,648 | 2,147,483,647 |
| 64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
Ventajas e inconvenientes
Ventajas del sistema binario
- Simple: Solo dos estados (0 y 1)
- Confiable: Fácil de implementar sin errores
- Eficiente: Óptimo para circuitos electrónicos
- Universal: Base de todos los sistemas digitales
Ventajas del sistema hexadecimal
- Compacto: 4 dígitos binarios = 1 dígito hexadecimal
- Legible: Más corto y claro que el binario
- Estándar: Ampliamente utilizado en programación
- Práctico: Ideal para direcciones y colores
Inconvenientes
- Abstracción: No intuitivo para las personas
- Conversión: Requiere aritmética mental
- Propenso a errores: Fácil equivocarse en conversiones manuales
Preguntas frecuentes de examen
1. **Convierta 175 (decimal) a binario y hexadecimal.**
175₁₀ = 10101111₂ = AF₁₆
2. **¿Cuál es el resultado de 12 & 10 (AND bit a bit)?**
12₁₀ = 1100₂, 10₁₀ = 1010₂ → 1100 & 1010 = 1000₂ = 8₁₀
3. **Explique el complemento a dos.**
Método para representar números negativos en binario mediante inversión de bits y suma de 1.
4. **¿Para qué se utilizan los números hexadecimales?**
Representación compacta de valores binarios, colores, direcciones de memoria, códigos de error.
Fuentes principales
- https://de.wikipedia.org/wiki/Zahlensystem
- https://de.wikipedia.org/wiki/Zweierkomplement
- https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html



