two second number binary bit-manipulation computer-science twos-complement data-representation

number - second complement binary



¿Qué es el "Complemento 2"? (17)

Estoy en un curso de sistemas informáticos y he estado luchando , en parte, con Complemento de Dos . Quiero entenderlo, pero todo lo que he leído no ha logrado unir la imagen para mí. He leído el artículo de wikipedia y otros artículos, incluido mi libro de texto .

Por lo tanto, quería comenzar esta publicación de la wiki de la comunidad para definir qué es el Complemento de Dos, cómo usarlo y cómo puede afectar a los números durante las operaciones como conversiones (de firmadas a no firmadas y viceversa), operaciones de bit-bit y operaciones de cambio de bit .

Lo que espero es una definición clara y concisa que sea fácilmente entendida por un programador.


Como la mayoría de las explicaciones que he visto, las anteriores son claras sobre cómo trabajar con el complemento de 2, pero no explican realmente lo que son matemáticamente. Trataré de hacer eso, al menos para los enteros, y cubriré algunos antecedentes que probablemente sean familiares primero.

Recuerda cómo funciona para decimal:
2345
es una forma de escribir
2 × 10 3 + 3 × 10 2 + 4 × 10 1 + 5 × 10 0 .

De la misma manera, binario es una forma de escribir números usando solo 0 y 1 siguiendo la misma idea general, pero reemplazando los 10 anteriores con 2s. Luego en binario,
1111
es una forma de escribir
1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0
y si lo resuelves, resulta que es igual a 15 (base 10). Eso es porque es
8 + 4 + 2 + 1 = 15.

Todo esto es bueno para los números positivos. Incluso funciona con números negativos si estás dispuesto a colocar un signo menos delante de ellos, como hacen los humanos con los números decimales. Incluso se puede hacer en las computadoras, pero no he visto una computadora así desde principios de los años 70. Os dejo los motivos para una discusión diferente.

Para las computadoras resulta más eficiente usar una representación de complemento para números negativos. Y aquí hay algo que a menudo se pasa por alto. Las notaciones complementarias implican algún tipo de inversión de los dígitos del número, incluso los ceros implícitos que vienen antes de un número positivo normal. Eso es incómodo, porque surge la pregunta: ¿todos ellos? Eso podría ser un número infinito de dígitos a considerar.

Afortunadamente, las computadoras no representan infinitos. Los números están restringidos a una longitud particular (o ancho, si lo prefiere). Así que volvamos a los números binarios positivos, pero con un tamaño particular. Usaré 8 dígitos ("bits") para estos ejemplos. Así que nuestro número binario sería realmente
00001111
o
0 × 2 7 + 0 × 2 6 + 0 × 2 5 + 0 × 2 4 + 1 × 2 3 + 1 × 2 2 + 1 × 2 1 + 1 × 2 0

Para formar el complemento negativo de 2, primero complementamos todos los dígitos (binarios) para formar
11110000
y agrega 1 a la forma
11110001
¿Pero cómo vamos a entender que significa -15?

La respuesta es que cambiamos el significado del bit de orden superior (el de la izquierda). Este bit será un 1 para todos los números negativos. El cambio será cambiar el signo de su contribución al valor del número en el que aparece. Así que ahora se entiende que nuestro 11110001 representa
- 1 × 2 7 + 1 × 2 6 + 1 × 2 5 + 1 × 2 4 + 0 × 2 3 + 0 × 2 2 + 0 × 2 1 + 1 × 2 0
Observe que "-" delante de esa expresión? Significa que el bit de signo lleva el peso -2 7 , que es -128 (base 10). Todas las demás posiciones conservan el mismo peso que tenían en números binarios sin firmar.

Trabajando nuestro -15, es
-128 + 64 + 32 + 16 + 1
Pruébalo en tu calculadora. es -15.

De las tres formas principales en que he visto los números negativos representados en las computadoras, el complemento de 2 gana la comodidad para uso general. Aunque tiene una rareza. Como es binario, tiene que haber un número par de combinaciones de bits posibles. Cada número positivo puede emparejarse con su negativo, pero solo hay un cero. Negar un cero te lleva a cero. Así que hay una combinación más, el número con 1 en el bit de signo y 0 en todas partes. El número positivo correspondiente no cabría en el número de bits que se utilizan.

Lo que es aún más extraño de este número es que si intentas formar su positivo complementando y agregando uno, obtienes el mismo número negativo. Parece natural que cero haría esto, pero esto es inesperado y no es en absoluto el comportamiento al que estamos acostumbrados porque, aparte de las computadoras, generalmente pensamos en un suministro ilimitado de dígitos, no en esta aritmética de longitud fija.

Esto es como la punta de un iceberg de rarezas. Hay más tumbados en espera debajo de la superficie, pero eso es suficiente para esta discusión. Probablemente podría encontrar más si investiga "desbordamiento" para la aritmética de punto fijo. Si realmente quieres entrar en él, también puedes buscar "aritmética modular".


Complementos de 2: Cuando agregamos uno adicional con los complementos de 1 de un número, obtendremos los complementos de 2. Por ejemplo: 100101 es el complemento de 1 es 011010 y el complemento de 2 es 011010 + 1 = 011011 (al agregar uno con el complemento de 1) Para obtener más información, este artículo lo explica gráficamente.


El complemento de 2 es muy útil para encontrar el valor de un binario, sin embargo, pensé en una forma mucho más concisa de resolver un problema de este tipo (nunca vi a nadie más publicarlo):

tome un binario, por ejemplo: 1101 que es [suponiendo que el espacio "1" es el signo] igual a -3 .

utilizando el complemento de 2 haríamos esto ... voltear 1101 a 0010 ... agregar 0001 + 0010 ===> nos da 0011. 0011 en binario positivo = 3. por lo tanto 1101 = -3 !

Lo que me di cuenta:

en lugar de todos los cambios y sumas, puedes hacer el método básico para resolver un binario positivo (digamos 0101) es (2 3 * 0) + (2 2 * 1) + (2 1 * 0) + (2 0 * 1) = 5.

¡Haz exactamente el mismo concepto con un negativo! (Con un pequeño giro)

tomar 1101, por ejemplo:

para el primer número en lugar de 2 3 * 1 = 8 , haga - (2 3 * 1) = -8 .

luego continúe como de costumbre, haciendo -8 + (2 2 * 1) + (2 1 * 0) + (2 0 * 1) = -3


El complemento de Two es una forma inteligente de almacenar enteros para que los problemas matemáticos comunes sean muy sencillos de implementar.

Para entender, hay que pensar en los números en binario.

Básicamente dice,

  • para cero, usa todos los 0''s.
  • para enteros positivos, comience a contar hacia arriba, con un máximo de 2 (número de bits - 1) -1.
  • para enteros negativos, haga exactamente lo mismo, pero cambie el rol de 0 y 1 (así que en lugar de comenzar con 0000, comience con 1111, esa es la parte del "complemento").

Intentémoslo con un mini-byte de 4 bits (lo llamaremos un nibble - 1/2 a byte).

  • 0000 - cero
  • 0001 - uno
  • 0010 - dos
  • 0011 - tres
  • 0100 a 0111 - cuatro a siete

Eso es todo lo que podemos llegar en positivo. 2 3 -1 = 7.

Para los negativos:

  • 1111 - uno negativo
  • 1110 - dos negativos
  • 1101 - tres negativos
  • 1100 a 1000 - negativo cuatro a negativo ocho

Tenga en cuenta que obtiene un valor adicional para los negativos ( 1000 = -8) que no para los positivos. Esto se debe a que 0000 se utiliza para cero. Esto puede ser considerado como línea de números de las computadoras.

Distinguir entre números positivos y negativos.

Al hacer esto, el primer bit toma el papel del bit de "signo", ya que puede usarse para distinguir entre valores decimales positivos y negativos. Si el bit más significativo es 1 , entonces se puede decir que el binario es negativo, mientras que si el bit más significativo (el extremo izquierdo) es 0 , puede decir que discernir el valor decimal es positivo.


Es un medio inteligente para codificar enteros negativos de tal manera que aproximadamente la mitad de la combinación de bits de un tipo de datos se reservan para enteros negativos, y la adición de la mayoría de los enteros negativos con sus correspondientes enteros positivos resulta en un desbordamiento de acarreo Eso deja el resultado como cero binario.

Entonces, en el complemento de 2, si uno es 0x0001, entonces -1 es 0x1111, ya que esto resultará en una suma combinada de 0x0000 (con un desbordamiento de 1).


Imagina que tienes un número finito de bits / trits / dígitos / lo que sea. Usted define 0 como todos los dígitos que son 0, y cuenta hacia arriba naturalmente:

00 01 02 ..

Eventualmente se desbordará.

98 99 00

Tenemos dos dígitos y podemos representar todos los números del 0 al 100. ¡Todos esos números son positivos! Supongamos que queremos representar números negativos también?

Lo que realmente tenemos es un ciclo. El número antes de 2 es 1. El número antes de 1 es 0. El número antes de 0 es ... 99 .

Entonces, para simplificar, digamos que cualquier número sobre 50 es negativo. "0" a "49" representan 0 a 49. "99" es -1, "98" es -2, ... "50" es -50.

Esta representación es el complemento de diez . Las computadoras normalmente usan el complemento de dos , que es el mismo, excepto que usan bits en lugar de dígitos.

Lo bueno del complemento de diez es que la adición simplemente funciona . ¡No necesita hacer nada especial para agregar números positivos y negativos!


La respuesta más simple:

1111 + 1 = (1) 0000. Entonces 1111 debe ser -1. Entonces -1 + 1 = 0.

Es perfecto para entender todo esto por mí.


Leí una explicación fantástica en Reddit por jng, usando el odómetro como una analogía.

Es una convención útil. Los mismos circuitos y operaciones lógicas que suman / restan números positivos en binario siguen funcionando tanto en números positivos como negativos si se usa la convención, por eso es tan útil y omnipresente.

Imagine el odómetro de un automóvil, gira en (digamos) 99999. Si incrementa 00000, obtiene 00001. Si disminuye 00000, obtiene 99999 (debido a la rotación). Si agrega uno de nuevo a 99999, vuelve a 00000. Por lo tanto, es útil decidir que 99999 representa -1. Del mismo modo, es muy útil decidir que 99998 representa -2, y así sucesivamente. Debe detenerse en algún lugar, y también por convención, la mitad superior de los números se considera negativa (50000-99999), y la mitad inferior positiva solo se destacan (00000-49999). Como resultado, el dígito superior que es 5-9 significa que el número representado es negativo, y que es 0-4 significa que el representado es positivo, exactamente igual que el bit superior que representa el signo en el número binario del complemento de dos.

Entender esto también fue difícil para mí. Una vez que lo obtuve y volví a leer los artículos y explicaciones de los libros (no había internet en ese entonces), resultó que muchos de los que lo describían no lo entendían realmente. Escribí un libro enseñando lenguaje ensamblador después de eso (que se vendió bastante bien durante 10 años).


Me gustó la respuesta de Lavinio, pero el cambio de bits agrega algo de complejidad. A menudo, existe la opción de mover bits mientras se respeta el bit de signo o no se respeta el bit de signo. Esta es la opción entre tratar los números como firmados (-8 a 7 para un nibble, -128 a 127 para bytes) o números sin signo de rango completo (0 a 15 para nibbles, 0 a 255 para bytes).


Me pregunto si podría explicarse mejor que el artículo de Wikipedia.

El problema básico que intenta resolver con la representación del complemento de dos es el problema de almacenar enteros negativos.

Primero considere un entero sin signo almacenado en 4 bits. Puedes tener los siguientes

0000 = 0 0001 = 1 0010 = 2 ... 1111 = 15

Estos no están firmados porque no hay ninguna indicación de si son negativos o positivos.

Magnitud de signo y notación excesiva

Para almacenar números negativos puedes probar varias cosas. Primero, puede usar la notación de magnitud de signo que asigna el primer bit como un bit de signo para representar +/- y los bits restantes para representar la magnitud. Entonces, usando 4 bits de nuevo y suponiendo que 1 significa - y 0 significa + entonces tienes

0000 = +0 0001 = +1 0010 = +2 ... 1000 = -0 1001 = -1 1111 = -7

Entonces, ¿ves el problema allí? Tenemos 0. positivo y negativo. El problema más grande es sumar y restar números binarios. Los circuitos para sumar y restar usando la magnitud de signo serán muy complejos.

Que es

0010 1001 + ----

?

Otro sistema es el exceso de notación . Puede almacenar números negativos, deshacerse del problema de los dos ceros, pero la suma y la resta siguen siendo difíciles.

Así que a lo largo viene el complemento de dos. Ahora puede almacenar números enteros positivos y negativos y realizar aritmética con relativa facilidad. Existen varios métodos para convertir un número en el complemento de dos. Aquí hay uno.

Convertir decimal al complemento de dos

  1. Convierta el número a binario (ignore el signo por ahora), por ejemplo, 5 es 0101 y -5 es 0101

  2. Si el número es un número positivo, entonces has terminado. por ejemplo, 5 es 0101 en binario usando dos notaciones de complemento.

  3. Si el número es negativo entonces

    3.1 encuentra el complemento (invierte 0 y 1), por ejemplo, -5 es 0101, por lo que encontrar el complemento es 1010

    3.2 Agregue 1 al complemento 1010 + 1 = 1011. Por lo tanto, -5 en el complemento a dos es 1011.

Entonces, ¿qué pasa si quisieras hacer 2 + (-3) en binario? 2 + (-3) es -1. ¿Qué tendrías que hacer si estuvieras usando la magnitud de signo para sumar estos números? 0010 + 1101 =?

Usando el complemento de dos, considera lo fácil que sería.

2 = 0010 -3 = 1101 + ------------- -1 = 1111

Convertir el complemento de dos a decimal

Convertir 1111 a decimal:

  1. El número comienza con 1, por lo que es negativo, por lo que encontramos el complemento de 1111, que es 0000.

  2. Suma 1 a 0000, y obtenemos 0001.

  3. Convertir 0001 a decimal, que es 1.

  4. Aplicar el signo = -1.

Tada!


Mirar el sistema de complemento de los dos desde un punto de vista matemático realmente tiene sentido. En el complemento de diez, la idea es esencialmente "aislar" la diferencia.

Ejemplo: 63 - 24 = x

Añadimos el complemento de 24 que es realmente justo (100 - 24). Realmente, todo lo que estamos haciendo es sumar 100 en ambos lados de la ecuación.

Ahora la ecuación es: 100 + 63 - 24 = x + 100, es por eso que eliminamos los 100 (o 10 o 1000 o lo que sea).

Debido a la inconveniente situación de tener que sustraer un número de una larga cadena de ceros, utilizamos un sistema de ''complemento de la raíz disminuida'', en el sistema decimal, el complemento de nueve.

Cuando se nos presenta un número restado de una gran cadena de nueves, solo necesitamos revertir los números.

Ejemplo: 99999 - 03275 = 96724

Esa es la razón, después del complemento de nueve, agregamos 1. Como probablemente sepa de matemáticas de la infancia, 9 se convierte en 10 por "robo" 1. Así que, básicamente, es solo el complemento de diez que toma 1 de la diferencia.

En Binario, el complemento de dos es equiparable al complemento de diez, mientras que el complemento de uno es complementario de dos. La principal diferencia es que, en lugar de tratar de aislar la diferencia con potencias de diez (sumando 10, 100, etc. en la ecuación), estamos tratando de aislar la diferencia con potencias de dos.

Es por este motivo que invertimos los bits. Al igual que nuestro minuendo es una cadena de nueves en decimal, nuestro minuendo es una cadena de unidades en binario.

Ejemplo: 111111 - 101001 = 010110

Debido a que las cadenas de unidades están 1 por debajo de una buena potencia de dos, "roban" 1 de la diferencia, como hacen las de nueve en decimal.

Cuando estamos usando números binarios negativos, estamos diciendo:

0000 - 0101 = x

1111 - 0101 = 1010

1111 + 0000 - 0101 = x + 1111

Para ''aislar'' x, necesitamos agregar 1 porque 1111 está a una distancia de 10000 y eliminamos el 1 principal porque lo agregamos a la diferencia original.

1111 + 1 + 0000 - 0101 = x + 1111 + 1

10000 + 0000 - 0101 = x + 10000

Simplemente retire 10000 de ambos lados para obtener x, es un álgebra básica.


Muchas de las respuestas hasta ahora explican muy bien por qué se utiliza el complemento de dos para representar un número negativo, pero no nos diga qué es el número de complemento de dos, en particular, no por qué se agrega un ''1'', y de hecho a menudo se agrega de manera incorrecta.

La confusión proviene de una mala comprensión de la definición de un número de complemento. Un complemento es la parte faltante que haría algo completo.

El complemento a la raíz de un n dígito número x en la raíz b es, por definición, b ^ nx. En binario, 4 se representa por 100, que tiene 3 dígitos (n = 3) y una raíz de 2 (b = 2). Así que su complemento radix es b ^ nx = 2 ^ 3-4 = 8-4 = 4 (o 100 en binario).

Sin embargo, en binario obtener un complemento de radix no es tan fácil como obtener su complemento de radix disminuido, que se define como (b ^ n-1) -y, solo 1 menos que el del complemento de radix. Para obtener un complemento de radix disminuido, simplemente voltea todos los dígitos.

100 -> 011 (complemento de la raíz disminuida (de uno))

para obtener el complemento radix (dos), simplemente agregamos 1, como se define en la definición.

011 +1 -> 100 (complemento a dos).

Ahora, con esta nueva comprensión, echemos un vistazo al ejemplo dado por Vincent Ramdhanie (ver la segunda respuesta anterior)

/ * comienzo de vicent

Convertir 1111 a decimal:

El número comienza con 1, por lo que es negativo, por lo que encontramos el complemento de 1111, que es 0000. Suma 1 a 0000, y obtenemos 0001. Convierte 0001 a decimal, que es 1. Aplica el signo = -1. Tada!

fin de Vicente * /

Debe entenderse como

El número comienza con 1, por lo que es negativo. Así que sabemos que es un complemento a dos de algún valor x. Para encontrar la x representada por el complemento de sus dos, primero necesitamos encontrar el complemento de 1.

complemento de dos de x: 1111 complemento de uno de x: 1111-1 -> 1110; x = 0001, (voltear todos los dígitos)

aplica el signo -, y la respuesta = -x = -1.


Permite obtener la respuesta 10 - 12 en formato binario usando 8 bits: Lo que realmente haremos es 10 + (-12)

Necesitamos obtener la parte complementaria de 12 para restarla de 10. 12 en binario es 00001100. 10 en binario es 00001010.

Para obtener la parte complementaria de 12, simplemente revertimos todos los bits y luego agregamos 1.12 en binario invertido es 11110011. Este es también el código inverso (complemento de uno). Ahora necesitamos agregar uno, que ahora es 11110100.

Así que 11110100 es el complemento de 12! Fácil cuando lo piensas de esta manera.

Ahora puedes resolver la pregunta anterior de 10-12 en forma binaria.

00001010 11110100 ----------------- 11111110



Se descubren dos complementos al agregar uno a uno de los complementos del número dado. Digamos que tenemos que encontrar dos complementos de 10101 luego encontrar su complemento, es decir, 01010 agregar 1 a este resultado, es decir, 01010+1=01011 , que es la respuesta final.



Tuve el mismo problema hace un par de semanas. Terminé leyendo sobre él en línea de varias fuentes, tratando de juntar las piezas y escribiendo sobre ello yo solo para asegurarme de que lo entendí correctamente. Usamos el complemento de dos principalmente por dos razones:

  1. Para evitar múltiples representaciones de 0
  2. Para evitar el seguimiento de la broca de acarreo (como en el complemento de uno) en caso de un desbordamiento.
  3. Realizar operaciones simples como la suma y la resta se vuelve fácil.

Si desea una explicación más detallada del asunto en cuestión, pruebe el artículo escrito por mí here . ¡Espero eso ayude!