Aritmética binaria y complemento a dos

Visualiza los pesos binarios, explora las representaciones con signo y sigue las operaciones por columnas.

Cargando simulación interactiva...

Un solo sumador también resta 🖖

En los ordenadores modernos, los enteros negativos se representan usando el Complemento a Dos. El bit más significativo (MSB) actúa como un peso negativo: para un entero de 8 bits, el bit 7 representa -128 en lugar de +128. La resta se vuelve idéntica a la suma: la CPU calcula A - B como A + (~B + 1), eliminando el hardware de sustracción separado y permitiendo a la ALU usar los mismos circuitos sumadores para ambas operaciones.

El binario es valor posicional en base 2 🖖

En los números cotidianos cada columna vale diez veces la de su derecha; en binario el factor es simplemente 2. Los bits llevan (de derecha a izquierda) los pesos 1, 2, 4, 8, 16, 32, … Leer un número binario consiste en sumar los pesos donde hay un 1: 1011 es 8 + 0 + 2 + 1 = 11. La pantalla de pesos de bits de la herramienta te deja alternar cada bit y ver el total acumulado, que es el secreto detrás de cada conversión aquí.

Tu CPU multiplica como un campesino ruso 🖖

La multiplicación larga que ves aquí —duplicar A y sumarlo allí donde B tiene un bit 1— es exactamente la "multiplicación del campesino ruso", un método que ya aparece en papiros egipcios de hace más de 3000 años. Se divide entre dos un número (descartando los restos) y se duplica el otro; luego se suman los valores duplicados donde el número reducido es impar. Dividir entre dos y comprobar la paridad es literalmente leer dígitos binarios, así que un antiguo escriba y una ALU moderna ejecutan el mismo algoritmo.

OCHO BITS, CUATRO SIGNIFICADOS — ¿QUÉ CODIFICACIÓN ESTÁS LEYENDO?

¿En qué codificación binaria estás?

Un byte no da ninguna pista sobre cómo leerlo. El patrón 11010110 es 214, o −42, o −41, o −86, dependiendo solo de un convenio acordado de antemano, y los bits por sí mismos no pueden decirte cuál. Elige mal y todo lo que venga después estará mal mientras todo sigue pareciendo correcto. Así que la primera pregunta nunca es cuál es el resultado, sino cuánto pesa el bit más alto. Las cuatro codificaciones de abajo responden a eso de cuatro maneras; los dos últimos casos muestran por qué una de ellas se ganó el hardware.

Sin signo — cada columna suma w₇ = +128 → 0…255
Complemento a dos — el bit alto te debe 128 w₇ = −128 → −128…127
Complemento a uno — negar invirtiendo cada bit w₇ = −127, 0 = ±0
Signo y magnitud — el bit que no es un número w₇ = ±, 0 = ±0
Resta sin restador a − b = a + (¬b + 1)
Multiplicar desplazando y sumando a × b = ∑ (a ≪ i)

01

Sin signo — cada columna suma

Qué sabes: Los ocho pesos son potencias positivas de dos, de 1 a 128. Nada codifica un signo, así que nada puede ser negativo: el rango es 0 a 255 y los 256 patrones están en uso.

Cómo leerlo: w₇ = +128 → 0…255

Ejemplo resuelto: 85 + 11 → 01010101 + 00001011 = 01100000 = 96, con los acarreos subiendo desde las columnas bajas. Empuja más y 214 + 100 da 58 en ocho bits: los verdaderos 314 menos 256, con el 1 que falta colgando en el acarreo de salida.

Abrir este caso: Suma sin signo
Sin signo — cada columna suma. Todos los pesos positivos: las ocho columnas simplemente suman, de 0 a 255. Los ocho pesos son potencias positivas de dos, de 1 a 128. Nada codifica un signo, así que nada puede ser negativo: el rango es 0 a 255 y los 256 patrones están en uso.
Todos los pesos positivos: las ocho columnas simplemente suman, de 0 a 255.

02

Complemento a dos — el bit alto te debe 128

Qué sabes: Siete pesos positivos y uno negativo: el bit 7 vale −128 en lugar de +128. Nada más cambia, y el rango se desplaza a −128 hasta 127.

Cómo leerlo: w₇ = −128 → −128…127

Ejemplo resuelto: 11010110 se descompone en −128 + 64 + 16 + 4 + 2 = −42. Suma 10 (00001010) con suma normal por columnas y obtienes 11100000 = −128 + 64 + 32 = −32. Esos mismos ocho bits son 214 en modo sin signo.

Abrir este caso: Complemento a dos
Complemento a dos — el bit alto te debe 128. El bit 7 pesa −128, así que 11010110 es −42: los bits que el modo sin signo llama 214. Siete pesos positivos y uno negativo: el bit 7 vale −128 en lugar de +128. Nada más cambia, y el rango se desplaza a −128 hasta 127.
El bit 7 pesa −128, así que 11010110 es −42: los bits que el modo sin signo llama 214.

03

Complemento a uno — negar invirtiendo cada bit

Qué sabes: El bit 7 pesa −127. Un número negativo es el inverso bit a bit de su magnitud, así que −42 es 11010101 y no 11010110, y el rango es simétrico: −127 a 127.

Cómo leerlo: w₇ = −127, 0 = ±0

Ejemplo resuelto: −42 es 11010101, el inverso de 00101010. Sumando 10 se llega a 11011111 = −127 + 64 + 16 + 8 + 4 + 2 + 1 = −32, y eso sale bien aquí solo porque nada salió por arriba. Prueba en cambio −42 + 50: la suma simple se lee como 7, uno menos, y el acarreo de salida tiene que volver a entrar por abajo para alcanzar el 8.

Abrir este caso: Complemento a uno
Complemento a uno — negar invirtiendo cada bit. −42 es simplemente 42 invertido, y 11111111 es un segundo cero, negativo. El bit 7 pesa −127. Un número negativo es el inverso bit a bit de su magnitud, así que −42 es 11010101 y no 11010110, y el rango es simétrico: −127 a 127.
−42 es simplemente 42 invertido, y 11111111 es un segundo cero, negativo.

04

Signo y magnitud — el bit que no es un número

Qué sabes: El bit 7 es una bandera pura sin peso alguno: 0 significa positivo, 1 significa negativo, y los siete bits bajos guardan una magnitud corriente de 0 a 127.

Cómo leerlo: w₇ = ±, 0 = ±0

Ejemplo resuelto: −42 es 10101010: el bit de signo puesto y después 42 como 0101010. Así escriben los números las personas, y es la única de las cuatro codificaciones en la que pasar ambos operandos a un sumador normal está simplemente mal: 10101010 + 00001010 sale como 10110100, que se lee como −52 y no como −32.

Abrir este caso: Signo y magnitud
Signo y magnitud — el bit que no es un número. El bit de signo no lleva peso, y un sumador normal devuelve −52 en lugar de −32. El bit 7 es una bandera pura sin peso alguno: 0 significa positivo, 1 significa negativo, y los siete bits bajos guardan una magnitud corriente de 0 a 127.
El bit de signo no lleva peso, y un sumador normal devuelve −52 en lugar de −32.

05

Resta sin restador

Qué sabes: Complemento a dos con la operación puesta en resta. El hardware no posee ningún circuito de resta: niega el segundo operando y suma.

Cómo leerlo: a − b = a + (¬b + 1)

Ejemplo resuelto: 42 − 58 → invierte 00111010 hasta 11000101, suma 1 para obtener 11000110, que es −58. Ahora súmale 00101010: 11110000, y eso se lee como −128 + 64 + 32 + 16 = −16.

Abrir este caso: Restar sumando
Resta sin restador. Invierte, suma uno y luego suma: 42 + (−58) cae en −16. Complemento a dos con la operación puesta en resta. El hardware no posee ningún circuito de resta: niega el segundo operando y suma.
Invierte, suma uno y luego suma: 42 + (−58) cae en −16.

06

Multiplicar desplazando y sumando

Qué sabes: Modo sin signo con la operación puesta en multiplicación. Cada bit 1 del segundo operando aporta una copia del primero, desplazada a la izquierda tantas posiciones como indique ese bit.

Cómo leerlo: a × b = ∑ (a ≪ i)

Ejemplo resuelto: 13 × 5 → el 5 es 00000101, así que están puestos los bits 0 y 2. Eso aporta 13 sin desplazar (00001101 = 13) más 13 desplazado dos veces (00110100 = 52), y 13 + 52 = 65 = 01000001.

Abrir este caso: Desplazar y sumar
Multiplicar desplazando y sumando. El 5 tiene puestos los bits 0 y 2, así que 13 y 52 son las únicas filas que cuentan. Modo sin signo con la operación puesta en multiplicación. Cada bit 1 del segundo operando aporta una copia del primero, desplazada a la izquierda tantas posiciones como indique ese bit.
El 5 tiene puestos los bits 0 y 2, así que 13 y 52 son las únicas filas que cuentan.

Problema resuelto al detalle

  1. Dos indicadores de desbordamiento distintos para el 42 convertido a ocho bits 6 pasos

    Convierte 42 a ocho bits de dos formas distintas y, a continuación, deduce por qué una CPU incluye dos banderas de desbordamiento independientes cuando solo dispone de un sumador.

    1. La notación posicional es una suma de potencias, por lo que la vía directa consiste en determinar qué potencias de dos están presentes. Con tres de ellas se obtiene directamente la secuencia de bits.

    2. El método mecánico ofrece la misma respuesta sin necesidad de buscar. Al dividir entre dos repetidamente, los restos son los bits, comenzando por el menos significativo: lea la columna hacia arriba.

    3. La negación en complemento a dos consiste en invertir y después incrementar, y el resultado equivale a 256 − 42. En eso consiste todo el truco: aritmética módulo 256, en la que la mitad superior se reetiqueta como negativa.

    4. Pasemos a las banderas. El acarreo de salida es una propiedad de la posición del bit más significativo; el desbordamiento es una discrepancia entre el acarreo de entrada al bit de signo y el acarreo de salida de este.

    5. Considere un par en el que las dos banderas no coinciden. No sale ningún acarreo del byte, por lo que la aritmética sin signo es correcta, pero el bit de signo ha cambiado: la respuesta con signo difiere en 256.

    6. Invierta la situación con un par que genere acarreo pero no desbordamiento, y el argumento a favor de las dos banderas queda demostrado.

    Respuesta

    Porque los mismos bits representan dos números distintos, y solo el programador sabe cuál. 0110 0100 + 0011 0010 = 1001 0110 no produce ningún acarreo de salida del bit 7, por lo que C = 0 y una lectura sin signo de 100 + 50 = 150 es perfectamente correcta. Si se interpreta el mismo resultado en complemento a dos, es −106, lo cual carece de sentido, y V = 1 así lo indica. Si en su lugar se suma 200 + 100, las banderas se intercambian: C = 1, V = 0. El sumador no lo sabe ni le importa: calcula una sola suma y activa ambas alarmas, y la instrucción que el compilador elija a continuación decide cuál de ellas es un error. Por esta razón, C y C++ dejan el desbordamiento con signo como no definido y definen el desbordamiento envolvente sin signo: el hardware los distingue y el lenguaje optó por exponer esa diferencia.

Referencias (1)

Problemas de ejemplo

  • Suma sin signo - 85 + 11 en binario, con el acarreo propagándose por las columnas.
  • Complemento a dos - Complemento a dos: 11010110 se lee como −42, y −42 + 10 = −32.
  • Complemento a uno - Complemento a uno: el bit alto pesa −127, así que −42 es 11010101.
  • Signo y magnitud - Signo y magnitud: el bit alto es puro signo, así que −42 es 10101010.
  • Restar sumando - 42 − 58 = −16, que ilustra cómo la resta se hace sumando gracias al peso negativo del bit alto.
  • Desplazar y sumar - 13 × 5 = 65 mediante multiplicación binaria de desplazar y sumar.