¿Cómo funciona el operador de complemento bit a bit de Python (~ tilde)?

9 minutos de lectura

avatar de usuario de bala
Bala

¿Por qué ~2 es igual a -3? Cómo ~ trabajo de operador?

Avatar de usuario de Anthony
Antonio

Recuerde que los números negativos se almacenan como complemento a dos de la contrapartida positiva. Como ejemplo, aquí está la representación de -2 en complemento a dos: (8 bits)

1111 1110

La forma de obtener esto es tomando la representación binaria de un número, tomando su complemento (invirtiendo todos los bits) y sumando uno. Dos comienza como 0000 0010, y al invertir los bits obtenemos 1111 1101. Sumando uno obtenemos el resultado anterior. El primer bit es el bit de signo, lo que implica un negativo.

Así que echemos un vistazo a cómo obtenemos ~2 = -3:

Aquí hay dos de nuevo:

0000 0010

Simplemente voltea todos los bits y obtenemos:

1111 1101

Bueno, ¿cómo se ve -3 en complemento a dos? Comience con 3 positivo: 0000 0011, cambie todos los bits a 1111 1100 y agregue uno para convertirse en valor negativo (-3), 1111 1101.

Entonces, si simplemente invierte los bits en 2, obtiene la representación del complemento a dos de -3.

El operador complemento (~) JUST FLIPS BITS. Depende de la máquina interpretar estos bits.

  • Otra cosa que se puede mencionar es que el flip se llama complemento a 1, antes de sumar el 1.

    – Chris S.

    26 de abril de 2009 a las 19:31

  • Podría ayudar a otros que no conocen el complemento de uno y el complemento de dos. Lea sobre ellos aquí. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement

    – Sai

    21 de diciembre de 2014 a las 3:40

  • ¿No es ese el operador bit a bit NO?

    – Braden Mejor

    20 de enero de 2015 a las 7:14

  • ¿Cómo sabe la máquina que está obteniendo un número negativo en complemento de dos en lugar de un número positivo más alto? ¿Se debe al sistema de tipos del idioma respectivo que indica que el tipo es un int con signo versus un sin signo?

    – GL2014

    20 de febrero de 2016 a las 22:05

  • @ GL2014 Creo que respondiste tu propia pregunta allí. Según tengo entendido, es cómo se diseñó la máquina para trabajar en primer lugar.

    – geekidharsh

    29 de julio de 2018 a las 19:45

avatar de usuario de driis
dris

~ voltea los bits en el valor.

Por qué ~2 es -3 tiene que ver con cómo los números se representan bit a bit. Los números se representan como complemento a dos.

Entonces, 2 es el valor binario

00000010

Y ~2 voltea los bits para que el valor sea ahora:

11111101

Cuál, es la representación binaria de -3.

  • ¿No es 11111101 == decimal 253 vs -3?

    – AKS

    07/08/2016 a las 10:00

  • Depende de si representa un entero con signo o sin signo.

    – driis

    07/08/2016 a las 17:50

  • ¿Cuál es su uso en la programación del mundo real? ¿Tiene aplicaciones en la programación competitiva?

    – Jprofundo

    17 de julio de 2020 a las 15:55


  • @driis, System.out.println((byte)(~2)); todavía genera -3 en lugar de 253, ¿puede explicar por qué?

    – cremallera

    16 de enero de 2021 a las 1:29

  • byte es un tipo firmado el rango es -128 .. 127

    – za-ek

    25 de noviembre de 2021 a las 19:58

Como otros mencionaron ~ solo volteó bits (cambia uno a cero y cero a uno) y desde complemento a dos se utiliza obtienes el resultado que viste.

Una cosa para agregar es por qué se utiliza el complemento a dos, esto es para que las operaciones sobre números negativos sean las mismas que sobre números positivos. Pensar en -3 como el número al que 3 debe agregarse para obtener cero y verá que este número es 1101recuerda que la suma binaria es como la suma de la escuela primaria (decimal), solo que llevas uno cuando llegas a dos en lugar de 10.

 1101 +
 0011 // 3
    =
10000
    =
 0000 // lose carry bit because integers have a constant number of bits.

Por lo tanto 1101 es -3voltea los bits que obtienes 0010 que es dos.

Esta operación es un complemento, no una negación.

Considere que ~0 = -1 y trabaje a partir de ahí.

El algoritmo para la negación es “complemento, incremento”.

¿Sabías? También existe el “complemento a uno” donde los números inversos son simétrico, y tiene un 0 y un -0.

Sé que la respuesta a esta pregunta se publicó hace mucho tiempo, pero quería compartir mi respuesta para lo mismo.

Para encontrar el complemento a uno de un número, primero encuentra su equivalente binario. Aquí, número decimal 2 se representa como 0000 0010 en forma binaria. Ahora tomando su complemento a uno invirtiendo (volteando todos los 1 en 0 y todos los 0 en 1) todos los dígitos de su representación binaria, lo que dará como resultado:

0000 0010 → 1111 1101

Este es el complemento a uno del número decimal 2. Y dado que el primer bit, es decir, el bit de signo es 1 en el número binario, significa que el signo es negativo por el número que almacenó. (aquí, el número al que se hace referencia es no 2 pero el complemento a uno de 2).

Ahora, dado que los números se almacenan como complemento a 2 (tomando el complemento a uno de un número más uno), para mostrar este número binario, 1111 1101a decimal, primero necesitamos encontrar su complemento a 2, que será:

1111 1101 → 0000 0010 + 1 → 0000 0011

Este es el complemento a 2. La representación decimal del número binario, 0000 0011es 3. Y, dado que el bit de signo era uno como se mencionó anteriormente, la respuesta resultante es -3.

Pista: Si lee atentamente este procedimiento, habrá observado que el resultado del operador complemento a uno es, en realidad, el número (operando – sobre el que se aplica este operador) más uno con signo negativo. También puedes probar esto con otros números.

  • ¿Por qué se suma dos veces? estoy viendo add, flip, add. 0010 -> 0011 -> 1100 -> 1101

    – Braden Mejor

    20 de enero de 2015 a las 7:45


  • Es voltear, voltear, agregar. Primera voltereta para complemento a 1. Y dado que está almacenado en complemento a 2 en el sistema, cuando necesite mostrar el número, mostrará el complemento a 2 del número almacenado (es decir, segundo volteo y suma).

    – Himanshu Aggarwal

    21 de enero de 2015 a las 14:45


  • ¿Pero no sería flip(flip(2)) solo 2? 0010 1101 0010

    – Braden Mejor

    21 de enero de 2015 a las 18:24

  • Si, serán solo 2. Pero dado que cuando los bits se almacenan en la memoria, el bit más significativo fue 1, lo que hará que el número sea negativo más adelante, como se explica en la respuesta anterior.

    – Himanshu Aggarwal

    22 de enero de 2015 a las 7:40

  • Por lo que estás describiendo y todo lo que he investigado, este no es un complemento de dos, sino un complemento “regular”, o un NO bit a bit. en lógica, NOT 0 = 1 y NOT 1 = 0. En un sistema de cuatro bits, NOT 0011 (3) = 1100 (12 sin firmar, -4 con firma). Por lo que entiendo, el complemento a dos se define como (NOT n) + 1, y se utiliza para encontrar la contrapartida negativa de un número independientemente del número de bits. De este modo, 2c(5) = -5. Mira, ahora tiene perfecto sentido. Siempre y cuando llame a esta operación por lo que es: un NO bit a bit.

    – Braden Mejor

    7 febrero 2015 a las 17:51


Avatar de usuario de Mike Aluydiav
Mike Aluydiav

int a=4; Sistema.salida.println(~a); El resultado sería :-5

‘~’ de cualquier entero en java representa el complemento a 1 del no. por ejemplo, estoy tomando ~4, lo que significa en representación binaria 0100. Primero, la longitud de un número entero es de cuatro bytes, es decir, 4*8 (8 bits por 1 byte) = 32. Entonces, en la memoria del sistema, 4 se representa como 0000 0000 0000 0000 0000 0000 0000 0100 ahora ~ el operador realizará el complemento a 1 en el binario anterior no

es decir, 1111 1111 1111 1111 1111 1111 1111 1011-> complemento de 1, el bit más significativo representa el signo del no (ya sea – o +) si es 1, entonces el signo es ‘-‘, si es 0, entonces el signo es ‘+’ según este nuestro resultado es un número negativo, en java los números negativos se almacenan en forma de complemento a 2, el resultado adquirido tenemos que convertirlo en complemento a 2 (primero realice el complemento a 1 y simplemente agregue 1 al complemento a 1). todos los uno se convertirán en ceros, excepto el bit más significativo 1 (que es nuestra representación de signo del número, lo que significa que para los 31 bits restantes 1111 1111 1111 1111 1111 1111 1111 1011 (resultado adquirido del operador ~) 1000 0000 0000 0000 0000 0000 0000 0100 (complemento a 1)

1 (complemento a 2)

1000 0000 0000 0000 0000 0000 0000 0101 ahora el resultado es -5 mira este enlace para ver el video https://youtu.be/w4pJ4cGWe9Y

  • ¿Por qué se suma dos veces? estoy viendo add, flip, add. 0010 -> 0011 -> 1100 -> 1101

    – Braden Mejor

    20 de enero de 2015 a las 7:45


  • Es voltear, voltear, agregar. Primera voltereta para complemento a 1. Y dado que está almacenado en complemento a 2 en el sistema, cuando necesite mostrar el número, mostrará el complemento a 2 del número almacenado (es decir, segundo volteo y suma).

    – Himanshu Aggarwal

    21 de enero de 2015 a las 14:45


  • ¿Pero no sería flip(flip(2)) solo 2? 0010 1101 0010

    – Braden Mejor

    21 de enero de 2015 a las 18:24

  • Si, serán solo 2. Pero dado que cuando los bits se almacenan en la memoria, el bit más significativo fue 1, lo que hará que el número sea negativo más adelante, como se explica en la respuesta anterior.

    – Himanshu Aggarwal

    22 de enero de 2015 a las 7:40

  • Por lo que estás describiendo y todo lo que he investigado, este no es un complemento de dos, sino un complemento “regular”, o un NO bit a bit. en lógica, NOT 0 = 1 y NOT 1 = 0. En un sistema de cuatro bits, NOT 0011 (3) = 1100 (12 sin firmar, -4 con firma). Por lo que entiendo, el complemento a dos se define como (NOT n) + 1, y se utiliza para encontrar la contrapartida negativa de un número independientemente del número de bits. De este modo, 2c(5) = -5. Mira, ahora tiene perfecto sentido. Siempre y cuando llame a esta operación por lo que es: un NO bit a bit.

    – Braden Mejor

    7 febrero 2015 a las 17:51


Simplemente ………..

Como complemento a 2 de cualquier número, podemos calcularlo invirtiendo todos los 1 en 0 y viceversa, de lo que le sumamos 1.

Aquí N= ~N produce resultados -(N+1) siempre. Porque el sistema almacena datos en forma de complemento a 2, lo que significa que almacena ~N así.

  ~N = -(~(~N)+1) =-(N+1). 

Por ejemplo::

  N = 10  = 1010
  Than ~N  = 0101
  so ~(~N) = 1010
  so ~(~N) +1 = 1011 

Ahora el punto es de donde viene Minus. Mi opinión es que supongamos que tenemos un registro de 32 bits, lo que significa 2 ^ 31 -1 bit involucrado en la operación y descansar un bit que cambia en el cálculo anterior (complemento) almacenado como bit de signo, que generalmente es 1. Y obtenemos el resultado como ~10 = -11.

~(-11) =10 ;

Lo anterior es cierto si printf(“%d”,~0); obtenemos resultado: -1;

Pero printf(“%u”,~0) que resultado: 4294967295 en una máquina de 32 bits.

¿Ha sido útil esta solución?