El complemento a dos, explicado

El binario no tiene signo menos. El complemento a dos es la convención que usa casi todo el hardware para representar enteros negativos, y en cuanto ves por qué se eligió, varias cosas confusas (como que −1 sea 0xFF) se vuelven obvias.

El problema: ¿dónde va el signo?

Con 8 bits puedes escribir 256 patrones. Si quieres números negativos, tienes que gastar algunos patrones en ellos. La idea ingenua —reservar el bit alto como bandera de signo y dejar el resto como magnitud— crea dos ceros (+0 y −0) y rompe la suma normal. El complemento a dos arregla ambas cosas.

La regla

Para negar un número: invierte todos los bits y suma uno. Para −42 en 8 bits:

  1. 42 = 0010 1010
  2. invertir → 1101 0101
  3. +1 → 1101 0110 = -42

El bit alto sigue indicando el signo —los patrones que empiezan por 1 son negativos—, pero no es solo una bandera: aporta el valor −2⁷. Formalmente, en 8 bits el bit de cabeza vale −128 y el resto potencias de dos positivas: 1101 0110 = −128 + 64 + 16 + 4 + 2 = −42.

Por qué −1 es todo unos

  1. 1 = 0000 0001
  2. invertir → 1111 1110
  3. +1 → 1111 1111 = -1

Por eso −1 se imprime como 0xFF en un byte, 0xFFFFFFFF en 32 bits y 0xFFFFFFFFFFFFFFFF en 64. La misma idea, con un registro más ancho.

Por qué al hardware le encanta

La suma simplemente funciona: -42 + 50 es una suma binaria normal de 1101 0110 + 0011 0010; el acarreo cae por el extremo y el resultado es 0000 1000 = 8. Sin circuitería especial para signos y sin menos-cero. La resta se convierte en «negar y sumar».

Desbordamiento: el rango es asimétrico

8 bits guardan de −128 a 127. Fíjate en la asimetría: existe −128 pero no +128. Si sumas 127 + 1 en aritmética de 8 bits con signo, das la vuelta hasta −128: eso es el desbordamiento con signo, el tipo de bug que se esconde hasta el peor momento. La app HexCalculator comprueba el desbordamiento de 64 bits en cada operación y muestra un error en lugar de un resultado envuelto en silencio.

Un patrón, dos significados

1101 0110 es −42 con signo y 214 sin signo. Los bits no saben cuál quieres decir: la interpretación es cosa tuya. Pruébalo en la calculadora de complemento a dos: muestra ambas lecturas lado a lado para cualquier ancho de 8 a 64 bits.

Extensión de signo

Ensanchar un valor con signo copia el bit de signo en los bits nuevos: −42 pasa de 1101 0110 (8 bits) a 1111 1111 1101 0110 (16 bits). Ensanchar un valor sin signo rellena con ceros. Confundir ambos es una fuente clásica de bugs del tipo «¿por qué mi número de repente es enorme?» al hacer casts en C.

Sigue explorando