Como o operador de complemento bit a bit (~ til) funciona?


Respostas:


282

Lembre-se de que os números negativos são armazenados como o complemento dos dois da contraparte positiva. Como exemplo, aqui está a representação de -2 no complemento de dois: (8 bits)

1111 1110

A maneira como você consegue isso é pegando a representação binária de um número, pegando seu complemento (invertendo todos os bits) e adicionando um. Duas partidas são 0000 0010 e, invertendo os bits, obtemos 1111 1101. A adição de uma nos dá o resultado acima. O primeiro bit é o bit de sinal, implicando um negativo.

Então, vamos dar uma olhada em como obtemos ~ 2 = -3:

Aqui estão dois novamente:

0000 0010

Basta virar todos os bits e obteremos:

1111 1101

Bem, como é -3 no complemento de dois? Comece com positivo 3: 0000 0011, vire todos os bits para 1111 1100 e adicione um para se tornar valor negativo (-3), 1111 1101.

Portanto, se você simplesmente inverter os bits em 2, obtém a representação do complemento dos dois em -3.

O operador complemento (~) APENAS FLIPS BITS. Cabe à máquina interpretar esses bits.


43
Uma outra coisa que talvez a mencionar é que o flip é chamado complemento 1s, antes de adicionar a 1.
Chris S

3
Pode ajudar outras pessoas que não estão cientes do complemento de um e do complemento de dois. Leia sobre eles aqui. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai

1
Esse não é o operador NOT bit a bit?
Braden Best

3
Como a máquina sabe que está recebendo um número negativo de dois complementos, em vez de um número positivo mais alto? É por causa do sistema de tipos do respectivo idioma, indicando que o tipo é um int assinado versus um não assinado?
GL2014

@ GL2014 Acho que você respondeu sua própria pergunta lá. No meu entendimento, é como a máquina foi projetada para funcionar em primeiro lugar.
Geekidharsh

40

~ vira os bits no valor.

Por que ~2é -3tem a ver com a forma como os números são representados bit a bit. Os números são representados como complemento de dois .

Então, 2 é o valor binário

00000010

E ~ 2 vira os bits para que o valor seja agora:

11111101

Qual é a representação binária de -3.


2
Não é 11111101 == decimal 253 vs -3?
AKS

10
Depende se representa um número inteiro assinado ou não assinado.
driis

18

Como outros mencionados, ~apenas trocamos bits (muda de um para zero e zero para um) e, como o complemento de dois é usado, você obtém o resultado que viu.

Uma coisa a acrescentar é por que o complemento de dois é usado, para que as operações em números negativos sejam as mesmas que em números positivos. Pense -3no número ao qual 3deve ser adicionado para obter zero e você verá que esse número é 1101, lembre-se de que a adição binária é como a adição da escola primária (decimal), somente você carrega um quando chega a dois em vez de 10 .

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

Portanto 1101é -3, inverter os bits que você começa 0010o que é dois.


8

Esta operação é um complemento, não uma negação.

Considere que ~ 0 = -1 e trabalhe a partir daí.

O algoritmo para negação é "complemento, incremento".

Você sabia? Há também o "complemento de alguém", onde os números inversos são simétricos e possuem um 0 e um -0.


6

Eu sei que a resposta para esta pergunta foi postada há muito tempo, mas eu queria compartilhar minha resposta pela mesma.

Para encontrar o complemento de um número, primeiro encontre seu equivalente binário. Aqui, o número decimal 2é representado como 0000 0010na forma binária. Agora, tomando o complemento de uma pessoa invertendo (invertendo todos os 1s em 0 e todos os 0s em 1s) todos os dígitos de sua representação binária, o que resultará em:

0000 0010 → 1111 1101

Este é o complemento do número decimal 2. E, como o primeiro bit, ou seja, o bit do sinal é 1 no número binário, significa que o sinal é negativo para o número armazenado. (aqui, o número referido não é 2, mas o complemento de 2).

Agora, como os números são armazenados como complemento de 2 (tomando o complemento de um número mais um), para exibir esse número binário 1111 1101, em decimal, primeiro precisamos encontrar o complemento de 2, que será:

1111 1101 → 0000 0010 + 1 → 0000 0011

Este é o complemento do 2. A representação decimal do número binário,, 0000 0011é 3. E, como o bit de sinal foi um como mencionado acima, a resposta resultante é -3.

Dica: Se você ler este procedimento cuidadosamente, teria observado que o resultado para o operador de complemento de alguém é, na verdade, o número (operando - no qual esse operador é aplicado) mais um com um sinal negativo. Você pode tentar isso com outros números também.


Por que está adicionando duas vezes? Eu estou vendo add, flip, add. 0010-> 0011-> 1100->1101
Braden Best

1
É virar, virar, adicionar. Primeiro toque para o complemento de 1. E, como ele é armazenado no complemento de 2 no sistema, quando você precisar exibir o número, ele mostrará o complemento de 2 no número armazenado (ou seja, segure o segundo e adicione).
Himanshu Aggarwal

Mas o flip (flip (2)) não seria apenas 2? 0010 1101 0010
Braden Best

Sim, serão apenas 2. Porém, como quando os bits são armazenados na memória, o bit mais significativo é 1, o que tornará o número negativo posteriormente, conforme explicado na resposta acima.
Himanshu Aggarwal

1
Pelo que você está descrevendo e por tudo o que pesquisei, esse não é um complemento de dois, mas um complemento "regular" ou NÃO. Na lógica, NOT 0 = 1e NOT 1 = 0. Em um sistema de quatro bits, NOT 0011(3) = 1100(12 não assinado, -4 assinado). Pelo que entendi, o complemento de dois é definido como (NOT n) + 1e é usado para encontrar a contrapartida negativa de um número, independentemente do número de bits. Assim 2c(5) = -5,. Veja, agora faz todo o sentido. Contanto que você chame esta operação do que é: um bit a bit NÃO.
Braden Best

4

int a = 4; System.out.println (~ a); O resultado seria: -5

'~' de qualquer número inteiro em java representa o complemento de 1 do não. por exemplo, estou usando ~ 4, o que significa na representação binária 0100. primeiro, o comprimento de um número inteiro é de quatro bytes, ou seja, 4 * 8 (8 bits para 1 byte) = 32. Portanto, na memória do sistema 4 é representado como 0000 0000 0000 0000 0000 0000 0000 0100 agora ~ o operador executará o complemento de 1 no número binário acima

ou seja, 1111 1111 1111 1111 1111 1111 1111 1011-> 1s complementam o bit mais significativo representa sinal de não (seja - ou +) se for 1, então sinal é '-' se for 0, então sinal é '+' conforme este resultado é um número negativo; em java, os números negativos são armazenados na forma de complemento de 2, o resultado adquirido temos que converter em complemento de 2 (primeiro execute o complemento de 1 e apenas adicione 1 ao complemento de 1). todos se tornarão zeros, exceto o bit 1 mais significativo (que é a representação do número do sinal, ou seja, para os 31 bits restantes 1111 1111 1111 1111 1111 1111 1111 1011 (resultado adquirido do operador ~) 1000 0000 0000 0000 0000 0000 0000 0100 (complemento 1)

1 (complemento de 2)

1000 0000 0000 0000 0000 0000 0000 0101 agora o resultado é -5, confira este link para o vídeo <[Operadores pouco inteligentes em java] https://youtu.be/w4pJ4cGWe9Y


2

Simplesmente ...........

Como complemento de 2 de qualquer número, podemos calcular invertendo todos os 1s para 0s e vice-versa do que adicionamos 1 a ele.

Aqui N = ~ N produz resultados - (N + 1) sempre. Como o sistema armazena dados em forma de complemento 2, o que significa que ele armazena ~ N assim.

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

Por exemplo::

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

Agora, o ponto é de onde vem Minus. Minha opinião é que temos um registro de 32 bits, o que significa 2 ^ 31 -1 bits envolvidos na operação e, para descansar um bit que muda no cálculo anterior (complemento) armazenado como bit de sinal que normalmente é 1. E obtemos resultado como ~ 10 = -11.

~ (-11) = 10;

O acima é verdadeiro se printf ("% d", ~ 0); nós obtemos resultado: -1;

Mas printf ("% u", ~ 0) que o resultado: 4294967295 na máquina de 32 bits.


1

O operador de complemento Bitwise (~) é um operador unário .

Funciona de acordo com os seguintes métodos

Primeiro, converte o número decimal fornecido no seu valor binário correspondente . No caso de 2, primeiro converte 2 para 0000 0010 (para o número binário de 8 bits).

Em seguida, converte todos os 1 no número para 0 e todos os zeros para 1; então, o número se tornará 1111 1101.

essa é a representação do complemento 2 de -3.

Para encontrar o valor não assinado usando o complemento, ou seja, simplesmente converter 1111 1101 em decimal (= 4294967293), podemos simplesmente usar o% u durante a impressão.


1

Eu acho que para a maioria das pessoas a parte da confusão vem da diferença entre o número decimal e o número binário assinado, então vamos esclarecer primeiro:

para o mundo decimal humano: 01 significa 1, -01 significa -1, para o mundo binário do computador: 101 significa 5 se não estiver assinado. 101 significa (-4 + 1) se for assinado enquanto o dígito assinado estiver na posição x. | x

então o bit invertido de 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 a confusão vem da mistura do resultado assinado (101 = -3) e do resultado não cantado (101 = 5)


1

tl; dr ~ vira os bits. Como resultado, o sinal muda. ~2é um número negativo ( 0b..101). A saída de um número negativo rubyimpressões -, então complemento de dois de ~2: -(~~2 + 1) == -(2 + 1) == 3. Números positivos são emitidos como estão.

Há um valor interno e sua representação em cadeia. Para números inteiros positivos, eles basicamente coincidem:

irb(main):001:0> '%i' % 2
=> "2"
irb(main):002:0> 2
=> 2

Sendo este último equivalente a:

irb(main):003:0> 2.to_s
"2"

~vira os bits do valor interno. 2é 0b010. ~2é 0b..101. Dois pontos ( ..) representam um número infinito de 1's. Como o bit mais significativo (MSB) do resultado é 1, o resultado é um número negativo ( (~2).negative? == true). Para a saída de um número negativo rubyimpressões -, então complemento do valor interno de dois. O complemento de dois é calculado invertendo os bits e adicionando 1. O complemento de dois de 0b..101é 3. Assim sendo:

irb(main):005:0> '%b' % 2
=> "10"
irb(main):006:0> '%b' % ~2
=> "..101"
irb(main):007:0> ~2
=> -3

Para resumir, ele vira os bits, o que muda o sinal. Para gerar um número negativo, imprime e -, em seguida ~~2 + 1( ~~2 == 2).

A razão pela qual rubygera números negativos dessa maneira é porque trata o valor armazenado como um complemento de dois do valor absoluto. Em outras palavras, o que é armazenado é 0b..101. É um número negativo e, como tal, é um complemento de dois de algum valor x. Para descobrir x, ele faz o complemento de dois 0b..101. Qual é o complemento de dois do complemento de dois de x. Qual é x(por exemplo ~(~2 + 1) + 1 == 2).

Caso você aplique ~a um número negativo, ele apenas inverte os bits (que, no entanto, altera o sinal):

irb(main):008:0> '%b' % -3
=> "..101"
irb(main):009:0> '%b' % ~-3
=> "10"
irb(main):010:0> ~-3
=> 2

O que é mais confuso é esse ~0xffffff00 != 0xff(ou qualquer outro valor com MSB igual a 1). Vamos simplificar um pouco: ~0xf0 != 0x0f. Isso porque trata 0xf0como um número positivo. O que realmente faz sentido. Então ~0xf0 == 0x..f0f,. O resultado é um número negativo. O complemento de dois de 0x..f0fé 0xf1. Assim:

irb(main):011:0> '%x' % ~0xf0
=> "..f0f"
irb(main):012:0> (~0xf0).to_s(16)
=> "-f1"

Caso você não aplique operadores bit a bit ao resultado, considere ~como um -x - 1operador:

irb(main):018:0> -2 - 1
=> -3
irb(main):019:0> --3 - 1
=> 2

Mas isso é indiscutivelmente inútil.

Um exemplo Digamos que você tenha uma máscara de rede de 8 bits (por simplicidade) e deseje calcular o número de 0's. Você pode calculá-los invertendo os bits e chamando bit_length( 0x0f.bit_length == 4). Mas ~0xf0 == 0x..f0f, portanto, temos que cortar os bits desnecessários:

irb(main):014:0> '%x' % (~0xf0 & 0xff)
=> "f"
irb(main):015:0> (~0xf0 & 0xff).bit_length
=> 4

Ou você pode usar o operador XOR ( ^):

irb(main):016:0> i = 0xf0
irb(main):017:0> '%x' % i ^ ((1 << i.bit_length) - 1)
=> "f"

0

Primeiro, temos que dividir o dígito fornecido em seus dígitos binários e, em seguida, revertê-lo, adicionando o último dígito binário. : A forma binária 2s é 00000010 muda para 11111101, este é um complemento e depois complementa 00000010 + 1 = 00000011, que é a forma binária de três e com -sign Ie, -3


0

O operador bit a bit é um operador unário que trabalha no método de sinal e magnitude de acordo com minha experiência e conhecimento.

Por exemplo, ~ 2 resultaria em -3.

Isso ocorre porque o operador bit a bit representaria primeiro o número em sinal e magnitude que é 0000 0010 (operador de 8 bits) em que o MSB é o bit de sinal.

Mais tarde, levaria o número negativo de 2, que é -2.

-2 é representado como 1000 0010 (operador de 8 bits) em sinal e magnitude.

Posteriormente, adiciona um 1 ao LSB (1000 0010 + 1), que fornece 1000 0011.

Qual é -3.


0

O til Javascript (~) força um determinado valor ao complemento - todos os bits são invertidos. Isso é tudo que o til faz. Não é sinal de opinião. Não adiciona nem subtrai qualquer quantidade.

0 -> 1
1 -> 0
...in every bit position [0...integer nbr of bits - 1]

Nos processadores de desktop padrão que usam linguagens de alto nível como JavaScript, a aritmética com assinatura BASE10 é a mais comum, mas lembre-se de que não é a única. Os bits no nível da CPU estão sujeitos a interpretação com base em vários fatores. No nível 'código', neste caso, JavaScript, eles são interpretados como um número inteiro assinado de 32 bits por definição (vamos deixar os flutuadores fora disso). Pense nisso como quântico, esses 32 bits representam muitos valores possíveis ao mesmo tempo. Depende inteiramente da lente de conversão pela qual você as vê.

JavaScript Tilde operation (1's complement)

BASE2 lens
~0001 -> 1110  - end result of ~ bitwise operation

BASE10 Signed lens (typical JS implementation)
~1  -> -2 

BASE10 Unsigned lens 
~1  -> 14 

Todas as alternativas acima são verdadeiras ao mesmo tempo.


0

Basicamente, a ação é um complemento, não uma negação.

Aqui x = ~ x produz resultados - (x + 1) sempre.

x = ~ 2

- (2 + 1)

-3

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.