Come funziona l'operatore di complemento bit a bit (~ tilde)?


Risposte:


282

Ricorda che i numeri negativi sono memorizzati come complemento a due della controparte positiva. Ad esempio, ecco la rappresentazione di -2 nel complemento a due: (8 bit)

1111 1110

Il modo in cui lo ottieni è prendendo la rappresentazione binaria di un numero, prendendo il suo complemento (invertendo tutti i bit) e aggiungendone uno. Due iniziano come 0000 0010 e invertendo i bit otteniamo 1111 1101. Aggiungendo uno otteniamo il risultato sopra. Il primo bit è il bit di segno, che implica un negativo.

Quindi diamo un'occhiata a come otteniamo ~ 2 = -3:

Eccone di nuovo due:

0000 0010

Basta capovolgere tutti i bit e otteniamo:

1111 1101

Bene, che aspetto ha -3 nel complemento a due? Inizia con 3: 0000 0011 positivi, capovolgi tutti i bit su 1111 1100 e aggiungine uno per diventare un valore negativo (-3), 1111 1101.

Quindi se semplicemente inverti i bit in 2, ottieni la rappresentazione del complemento a due di -3.

L'operatore del complemento (~) JUST FLIPS BITS. Spetta alla macchina interpretare questi bit.


43
Un'altra cosa forse da menzionare è che il flip si chiama complemento 1, prima di aggiungere l'1.
Chris S

3
Potrebbe aiutare gli altri che non sono a conoscenza del Complemento di One e del Complemento di Two. Leggi su di loro qui. en.wikipedia.org/wiki/Ones%27_complement en.wikipedia.org/wiki/Two%27s_complement
Sai,

1
Non è l'operatore bit a bit NOT?
Braden Best

3
Come fa la macchina a sapere che sta ottenendo un numero negativo a due complementi anziché un numero positivo più alto? È a causa del sistema di tipi della rispettiva lingua che indica che il tipo è un segno int rispetto a un segno?
GL2014,

@ GL2014 Penso che tu abbia risposto alla tua domanda lì. A mio avviso, è come la macchina è stata progettata per funzionare in primo luogo.
geekidharsh,

40

~ inverte i bit nel valore.

Perchè ~2è -3ha a che fare con il modo in numeri sono rappresentati bit a bit. I numeri sono rappresentati come complemento a due .

Quindi, 2 è il valore binario

00000010

E ~ 2 lancia i bit in modo che il valore sia ora:

11111101

Quale, è la rappresentazione binaria di -3.


2
11111101 == decimale 253 vs -3?
AKS

10
Dipende se rappresenta un numero intero con o senza segno.
driis,

18

Come altri hanno menzionato ~solo i bit capovolti (cambia da uno a zero e da zero a uno) e poiché viene utilizzato il complemento a due ottieni il risultato che hai visto.

Una cosa da aggiungere è il motivo per cui vengono utilizzati i complementi di due, in modo che le operazioni sui numeri negativi siano le stesse dei numeri positivi. Pensa -3al numero a cui 3dovrebbe essere aggiunto per ottenere zero e vedrai che questo numero è 1101, ricorda che l'aggiunta binaria è proprio come l'aggiunta alla scuola elementare (decimale) che ne porti solo una quando arrivi a due anziché a 10 .

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

Pertanto 1101è -3, capovolgere i bit si ottiene 0010che è due.


8

Questa operazione è un complemento, non una negazione.

Considera che ~ 0 = -1, e lavora da lì.

L'algoritmo per la negazione è "complemento, incremento".

Lo sapevate? C'è anche un "complemento" in cui i numeri inversi sono simmetrici e ha sia uno 0 che uno -0.


6

So che la risposta a questa domanda è stata pubblicata molto tempo fa, ma volevo condividere la mia risposta per lo stesso.

Per trovare il complemento di un numero, trova prima il suo equivalente binario. Qui, il numero decimale 2è rappresentato come 0000 0010in forma binaria. Ora prendendo il proprio complemento invertendo (capovolgendo tutti gli 1 in 0 e tutti gli 0 in 1) tutte le cifre della sua rappresentazione binaria, che si tradurrà in:

0000 0010 → 1111 1101

Questo è il complemento per il numero decimale 2. Dal momento che il primo bit, ovvero il bit del segno è 1 nel numero binario, significa che il segno è negativo per il numero memorizzato. (qui, il numero indicato non è 2 ma il complemento di 2).

Ora, poiché i numeri sono memorizzati come complemento di 2 (prendendo il complemento di un numero più uno), quindi per visualizzare questo numero binario 1111 1101, in decimale, prima dobbiamo trovare il complemento di 2, che sarà:

1111 1101 → 0000 0010 + 1 → 0000 0011

Questo è il complemento a 2. La rappresentazione decimale del numero binario 0000 0011, è 3. E, poiché il bit di segno era uno come menzionato sopra, quindi la risposta risultante è -3.

Suggerimento: se leggi attentamente questa procedura, allora avresti osservato che il risultato per l'operatore del complemento è effettivamente il numero (operando - su cui viene applicato questo operatore) più uno con un segno negativo. Puoi provarlo anche con altri numeri.


Perché aggiunge due volte? Sto vedendo add, flip, add. 0010-> 0011-> 1100->1101
Braden Best

1
È capovolgere, capovolgere, aggiungere. Primo capovolgimento per il complemento di 1. E poiché, è memorizzato nel complemento di 2 nel sistema, quando è necessario visualizzare il numero, mostrerà il complemento di 2 del numero memorizzato (cioè, seconda capovolgi e aggiungi).
Himanshu Aggarwal,

Ma Flip (Flip (2)) non sarebbe solo 2? 0010 1101 0010
Braden Best

Sì, saranno solo 2. Ma da quando i bit sono memorizzati nella memoria il bit più significativo era 1, il che renderà il numero negativo in seguito, come spiegato nella risposta sopra.
Himanshu Aggarwal il

1
Da quello che stai descrivendo e da tutto ciò che ho studiato, questo non è un complemento a due, ma un complemento "normale", o un NOT bit a bit. In logica NOT 0 = 1e NOT 1 = 0. In un sistema a quattro bit, NOT 0011(3) = 1100(12 senza segno, -4 con segno). Da quello che ho capito, il complemento a due è definito come (NOT n) + 1, ed è usato per trovare la controparte negativa di un numero indipendentemente dal numero di bit. Così, 2c(5) = -5. Vedi, ora ha perfettamente senso. Fintanto che chiamate questa operazione, cos'è: un NOT bit a bit.
Braden Best

4

int a = 4; System.out.println (~ a); Il risultato sarebbe: -5

'~' di qualsiasi numero intero in Java rappresenta il complemento di 1 del no. per esempio sto prendendo ~ 4, che significa nella rappresentazione binaria 0100. in primo luogo, la lunghezza di un numero intero è di quattro byte, cioè 4 * 8 (8 bit per 1 byte) = 32. Quindi nella memoria di sistema 4 è rappresentato come 0000 0000 0000 0000 0000 0000 0000 0100 ora ~ l'operatore eseguirà il complemento di 1 sul binario sopra no

cioè 1111 1111 1111 1111 1111 1111 1111 1011-> 1 complemento il bit più significativo rappresenta il segno del no (o - o +) se è 1 allora il segno è '-' se è 0 allora il segno è '+' come da questo nostro risultato è un numero negativo, in java i numeri negativi sono memorizzati nella forma del complemento di 2, il risultato acquisito dobbiamo convertire nel complemento di 2 (esegui prima il complemento di 1 e aggiungi solo il complemento di 1 a 1). tutti diventeranno zeri, tranne il bit 1 più significativo (che è la nostra rappresentazione del segno del numero, ciò significa che restano 31 bit 1111 1111 1111 1111 1111 1111 1111 1011 (risultato acquisito di ~ operatore) 1000 0000 0000 0000 0000 0000 0000 0100 (complemento a 1)

1 (complemento a 2)

1000 0000 0000 0000 0000 0000 0000 0101 ora il risultato è -5 controlla questo link per il video <[Operatori saggi di bit in Java] https://youtu.be/w4pJ4cGWe9Y


2

Semplicemente ...........

Come complemento di 2 di qualsiasi numero, possiamo calcolare invertendo tutti 1 da 0 a e viceversa di quanto ne aggiungiamo 1.

Qui N = ~ N produce risultati - (N + 1) sempre. Perché il sistema memorizza i dati in forma di complemento di 2, il che significa che memorizza ~ N in questo modo.

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

Per esempio::

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

Ora il punto è da dove viene Minus. La mia opinione è supponiamo di avere un registro a 32 bit che significa 2 ^ 31 -1 bit coinvolti nel funzionamento e di riposare un bit che cambia nel calcolo precedente (complemento) memorizzato come bit di segno che è 1 di solito. E otteniamo il risultato come ~ 10 = -11.

~ (-11) = 10;

Quanto sopra è vero se printf ("% d", ~ 0); otteniamo il risultato: -1;

Ma printf ("% u", ~ 0) del risultato: 4294967295 su macchina a 32 bit.


1

L'operatore del complemento Bitwise (~) è un operatore unario .

Funziona secondo i seguenti metodi

Per prima cosa converte il numero decimale dato nel corrispondente valore binario. In caso di 2, per prima cosa converte 2 in 0000 0010 (in numero binario a 8 bit).

Quindi converte tutti gli 1 nel numero in 0 e tutti gli zeri in 1; quindi il numero diventerà 1111 1101.

questa è la rappresentazione del complemento a 2 di -3.

Per trovare il valore senza segno usando complemento, cioè semplicemente per convertire da 1111 1101 in decimale (= 4294967293) possiamo semplicemente usare% u durante la stampa.


1

Penso che per la maggior parte delle persone la parte di confusione derivi dalla differenza tra il numero decimale e il numero binario con segno, quindi chiariamolo prima:

per il mondo decimale umano: 01 significa 1, -01 significa -1, per il mondo binario del computer: 101 significa 5 se non è firmato. 101 significa (-4 + 1) se è firmato mentre la cifra firmata è nella posizione x. | X

quindi il bit capovolto di 2 = ~ 2 = ~ (010) = 101 = -4 + 1 = -3 la confusione deriva dalla confusione del risultato con segno (101 = -3) e del risultato senza segno (101 = 5)


1

tl; dr ~ lancia i bit. Di conseguenza il segno cambia. ~2è un numero negativo ( 0b..101). Per produrre un numero negativo rubystampe -, poi due di complemento di ~2: -(~~2 + 1) == -(2 + 1) == 3. I numeri positivi vengono emessi così come sono.

C'è un valore interno e la sua rappresentazione di stringa. Per numeri interi positivi, sostanzialmente coincidono:

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

Quest'ultimo equivale a:

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

~inverte i bit del valore interno. 2lo è 0b010. ~2lo è 0b..101. Due punti ( ..) rappresentano un numero infinito di 1's. Poiché il bit più significativo (MSB) del risultato è 1, il risultato è un numero negativo ( (~2).negative? == true). Per produrre un numero negativo rubystampe -, quindi complemento a due del valore interno. Il complemento a due viene calcolato lanciando i bit, quindi aggiungendo 1. Il complemento a due di 0b..101è 3. Come tale:

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

Per riassumere, capovolge i bit, cambiando il segno. Per generare un numero negativo, stampa -, quindi ~~2 + 1( ~~2 == 2).

Il motivo per cui rubygenera numeri negativi in ​​questo modo è perché tratta il valore memorizzato come un complemento a due del valore assoluto. In altre parole, ciò che è memorizzato è 0b..101. È un numero negativo e come tale è un complemento a due di un certo valore x. Per trovare x, fa il complemento di due 0b..101. Che è il complemento di due del complemento di due di x. Quale è x(ad esempio ~(~2 + 1) + 1 == 2).

Nel caso in cui si applichi ~a un numero negativo, capovolge semplicemente i bit (che tuttavia cambia il segno):

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

Ciò che è più confuso è che ~0xffffff00 != 0xff(o qualsiasi altro valore con MSB uguale a 1). Semplificiamo un po ': ~0xf0 != 0x0f. Questo perché considera 0xf0un numero positivo. Il che ha davvero senso. Quindi ~0xf0 == 0x..f0f. Il risultato è un numero negativo. Il complemento a due di 0x..f0fè 0xf1. Così:

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

Nel caso in cui non applicherai operatori bit a bit al risultato, puoi considerare ~come -x - 1operatore:

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

Ma questo è probabilmente inutile.

Un esempio Supponiamo che ti venga fornita una maschera di rete a 8 bit (per semplicità) e desideri calcolare il numero di 0. Puoi calcolarli lanciando i bit e chiamando bit_length( 0x0f.bit_length == 4). Ma ~0xf0 == 0x..f0f, quindi, dobbiamo tagliare i pezzi non necessari:

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

Oppure puoi usare l'operatore XOR ( ^):

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

0

Per prima cosa dobbiamo dividere la cifra data nelle sue cifre binarie e poi invertirla aggiungendola all'ultima cifra binaria. Dopo questa esecuzione dobbiamo dare un segno opposto alla cifra precedente quella che stiamo trovando conforme ~ 2 = -3 Spiegazione : La forma binaria 2s è 00000010 cambia in 11111101 questo è un complemento, quindi 00000010 + 1 = 00000011, che è la forma binaria di tre e con -sign Ie, -3


0

L'operatore bit-saggio è un operatore unario che lavora sul metodo del segno e della grandezza secondo la mia esperienza e conoscenza.

Ad esempio ~ 2 comporterebbe -3.

Questo perché l'operatore bit-saggio rappresenterebbe prima il numero in segno e magnitudine che è 0000 0010 (operatore a 8 bit) dove MSB è il bit del segno.

Quindi in seguito ci vorrebbe il numero negativo di 2 che è -2.

-2 è rappresentato come 1000 0010 (operatore a 8 bit) in segno e grandezza.

Successivamente aggiunge un 1 all'LSB (1000 0010 + 1) che ti dà 1000 0011.

Che è -3.


0

Javascript tilde (~) costringe un dato valore al complemento di ognuno - tutti i bit sono invertiti. È tutto ciò che fa Tilde. Non è segno supponente. Non aggiunge né sottrae alcuna quantità.

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

Su processori desktop standard che utilizzano linguaggi di alto livello come JavaScript, l'aritmetica firmata BASE10 è la più comune, ma tieni presente che non è l'unico tipo. I bit a livello di CPU sono soggetti a interpretazione basata su una serie di fattori. A livello di 'codice', in questo caso JavaScript, vengono interpretati come un intero con segno a 32 bit per definizione (lasciamo fuori i float). Pensalo come quantistico, quei 32 bit rappresentano molti possibili valori contemporaneamente. Dipende interamente dall'obiettivo di conversione in cui li vedi.

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 

Tutto quanto sopra è vero allo stesso tempo.


0

Fondamentalmente l'azione è un complemento, non una negazione.

Qui x = ~ x produce risultati - (x + 1) sempre.

x = ~ 2

- (2 + 1)

-3

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.