2012-11-23 18 views
11

Recentemente ho frequentato un corso di Java (corso intensivo della durata di 1 settimana) e abbiamo coperto alcuni aspetti matematici binari.Unario operatore "~" - Cosa sta succedendo esattamente qui?

Questo ~ operatore unario (tilde credo che si chiama?) È stato spiegato a noi così:

inverte lo schema di bit trasformando ogni "0" in un "1" ed ogni "1" in una " 0" . ad es. Ci sono 8 bit per un byte. Se si ha il seguente byte: 00000000 il valore invertito cambierebbe per diventare 11111111.

La spiegazione di cui sopra è chiara e concisa, e totalmente sensata per me. Finché, cioè, cerco di implementarlo.

Dato questo:

byte x = 3; 
byte y = 5; 
System.out.println(~x); 
System.out.println(~y); 

L'output è:

-4 
-6 

Sono molto confuso su come questo accade.

Se +3 in binario è 11, l'inversione di questo sarebbe 00, che chiaramente non è -3.

Ma come ci sono 8 bit in un byte, allora la rappresentazione binaria di +3 non dovrebbe essere scritta come 00000011?

Quale sarebbe invertito per diventare 11111100. Convertito di nuovo in valore decimale questo sarebbe 252. Se tuttavia si scrive il +3 come 011, quindi converte effettivamente in 100, che è +4, ma come si fa sai che è un numero negativo?

Che ne dici se provi 0011, che converte in 1100, che se usi il primo bit come segno, allora diventa effettivamente -4.

Ah, quindi a questo punto ho pensato di arrivare da qualche parte.

Ma poi sono arrivato al secondo valore di y = 5.

Come scriviamo questo? Usando la stessa logica, +5 converte in binario 0101, che inverte in 1010.

Ed è ora che sono orribilmente confuso. Questo sembra rappresentare un valore con segno di -2 o un valore senza segno di +10 decimale? Nessuno dei due è il -6 che sto stampando.

Ancora, se aumento la lunghezza fino alle 8 cifre di un byte, +5 è 00000101, che diventa invertito 11111010. E davvero non riesco a trovare un modo per trasformarlo in -6.

Qualcuno là fuori lo capisce, perché non ho idea di cosa stia succedendo qui e più numeri che stampo più divento confuso.

Google non sembra venire con qualsiasi cosa molto su questo - forse non gli piace guardare piccoli segni operatore .. :-(

+2

Tutti i tipi numerici integrali in Java sono * firmati *. –

+2

@MarkoTopolnik char è un tipo numerico e non è firmato. –

+0

Dopo tutte le risposte molto utili per quanto riguarda il complemento a 2, ho trovato questo video che sembra spiegarlo abbastanza bene. Grazie a tutti coloro che hanno risposto. http://www.youtube.com/watch?v=Hof95YlLQk0&NR=1&feature=endscreen –

risposta

4

Da wikipedia: Nella notazione complemento a due, un numero non negativo è rappresentato dalla sua rappresentazione binaria ordinaria; in questo caso, il bit più significativo è 0. L'operazione di complemento a due è l'operazione di negazione, quindi i numeri negativi sono rappresentati dal complemento a due del valore assoluto.
Per ottenere il complemento a due di un numero binario, i bit sono invertiti o "capovolti", utilizzando l'operazione NOT bit a bit; il valore di 1 viene quindi aggiunto al valore risultante, ignorando l'overflow che si verifica quando si acquisisce il complemento di 0. 0. http://en.wikipedia.org/wiki/Two%27s_complement

Quindi se si ha 0101 che è +5 l'inverso di quello è 1010, che è -5 .

In realtà non si legge l'010 come un 5, ma quando si vede il 1 all'inizio, si sa che per ottenere il numero è necessario invertire nuovamente il resto delle cifre per ottenere il numero positivo che vuoi negare. Se questo ha un senso.

È un concetto un po 'alieno se prima non si è lavorato con esso. Non è certamente il modo in cui funzionano i numeri decimali, ma in realtà è semplice una volta che vedi cosa sta succedendo.

Un valore di 8 decimale viene scritto come 01010, che nega a 10101. La prima cifra (1) significa che è negativo, e poi capovolgere lo schienale per ottenere il valore numerico: 1010.

Una cosa ricordare che il complemento di Due non è lo stesso del normale conteggio di vecchi sistemi binari. Nel normale binario il valore di 10101 (che nel complemento a due è -8 come sopra) è ovviamente 21. Immagino che questo sia il punto in cui arriva la confusione - come si fa a distinguere guardandole? È necessario sapere quale rappresentazione è stata utilizzata per decidere quale sia effettivamente il valore del numero. C'è anche il complemento di Uno che differisce leggermente.

Un buon tutorial sulla matematica binarie, tra cui il complemento di uno e due di è dato qui. http://www.math.grin.edu/~rebelsky/Courses/152/97F/Readings/student-binary

+0

Oh capisco. Stavo cercando di leggerli come numeri positivi, ma con un 1 davanti. Grazie per quello. Anche per i link - sono geniali. Finalmente lo capisco adesso. Credo. :-) –

+0

Voglio aggiungere che tutto questo avviene in valori a 32 bit. Quindi, quando hai detto 3, era effettivamente in binario 00000000000000000000000000000011. Quando l'hai invertito diventa 11111111111111111111111111111100 che equivale a -4 nella parola a 32 bit a complemento di due. –

7

Vedere questa dimostrazione: -

3 -> 0011 
~3 -> 1100 -> -4 (2's complement) 

5 -> 0101 
~5 -> 1010 -> -6 (2's complement) 

Poiché gli interi con segno sono memorizzati come complemento a 2, prendere 2's complement di 1100 ti dà 4. Ora dal 1100 è un numero negativo.Quindi, il risultato è -4. Lo stesso è il caso con 1010.

1100 
0011 - 1's complement 
0100 - 2's complement - value = 4 (take negative) 
+1

Inoltre, si noti che l'operatore di complemento bit per bit esegue una promozione numerica unaria. –

+0

Complemento a 2. Hmm. Il nostro allenatore non ha menzionato quel po '. Off a Google vado. Grazie. :-) –

2

interi con segno sono quasi universalmente memorizzati utilizzando twos complement. Ciò significa invertire i bit (prendendo il complemento a uno) e aggiungerne uno. In questo modo non si hanno due rappresentazioni del numero intero zero (+0 e -0) e alcune operazioni firmate diventano più facili da implementare nell'hardware.

2

Java utilizza i numeri firmato nel Two's complement. Il tuo ragionamento sarebbe corretto in C o in altre lingue quando si usano tipi come "unsigned int" o "unsigned char".

Problemi correlati