bitlvl
IT

Convertitore di complemento a due

Scrivi un numero decimale (anche negativo) o uno schema di bit in binario o hex e guarda come viene memorizzato e letto nella larghezza scelta.

Larghezza
bit di segno

I risultati e i messaggi di questo strumento sono mostrati in inglese.

Come funziona il complemento a due

I computer non hanno il segno meno, solo bit. Il complemento a due è la convenzione che quasi ogni CPU usa per memorizzare interi negativi: il bit più alto (il bit di segno) conta come 2ⁿ⁻¹ negativo invece che positivo. A 8 bit, il bit più alto vale −128, quindi 1111 1111 = −128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = −1, e 1000 0000 è −128.

Gli stessi bit letti senza segno sono 255 e 128. Se un valore è «davvero» negativo lo decide il tipo nel tuo codice (int8_t contro uint8_t), non i bit. Per questo questo strumento mostra sempre entrambe le letture.

Negare un numero a mano

  1. Scrivi il valore positivo in binario alla larghezza piena (42 = 0010 1010).
  2. Inverti ogni bit (1101 0101).
  3. Aggiungi 1 (1101 0110). Questo è −42, cioè 0xD6 o 214 senza segno.

Il trucco funziona in entrambe le direzioni: applicato a −42 restituisce 42. Lo strumento qui sopra mostra questi passaggi per qualsiasi input.

Perché è progettato così

Con il complemento a due l’hardware non ha bisogno di un sottrattore separato. Sommare un numero negativo è una normale addizione binaria in cui si scarta il riporto dal bit più alto: 42 + (−42) = 0010 1010 + 1101 0110 = 1 0000 0000, si scarta il nono bit, risultato 0. Inoltre c’è un solo zero, a differenza del segno-modulo o del complemento a uno.

Intervalli di valori

LarghezzaCon segnoSenza segnoTipo tipico
8−128 … 1270 … 255int8_t, byte
16−32.768 … 32.7670 … 65.535int16_t, short
32−2.147.483.648 … 2.147.483.6470 … 4.294.967.295int32_t, int
64−9,22 × 10¹⁸ … 9,22 × 10¹⁸0 … 1,84 × 10¹⁹int64_t, long

L’intervallo negativo è più grande di uno rispetto a quello positivo perché lo zero occupa uno degli schemi «positivi». Per questo -INT_MIN va in overflow: 128 non sta in un byte con segno.

Domande

Quanto fa −1 in complemento a due?

Tutti uno: 0xFF a 8 bit, 0xFFFF a 16, 0xFFFFFFFF a 32. Invertendo 0000 0001 si ottiene 1111 1110, aggiungendo 1 si ottiene 1111 1111.

Come capisco se un numero binario è negativo?

Dal bit più a sinistra nella larghezza dichiarata. Se è 1 e il valore ha il segno, il numero è negativo. 1000 0000 è −128 come int8 ma 128 come uint8; i bit da soli non lo decidono.

Perché 127 + 1 dà −128?

Overflow con segno. 0111 1111 + 1 = 1000 0000, che imposta il bit di segno. In C è comportamento indefinito; nella maggior parte degli altri linguaggi il valore gira a −128.

Cos’è l’estensione del segno?

Allargare un valore con segno copiando il bit di segno nei nuovi bit alti, così −1 (0xFF) diventa 0xFFFF, non 0x00FF. Un cast da int8 a int16 lo fa automaticamente; un cast di un valore senza segno riempie invece con zeri. Cambia la larghezza qui sopra con un numero negativo inserito per vederlo.

Il bit di segno è solo un flag?

No. In complemento a due il bit di segno ha un valore (−2ⁿ⁻¹) e partecipa all’aritmetica. Questo lo distingue dal segno-modulo, dove il bit alto segna solo il segno, e dalla virgola mobile, dove il segno è un flag a parte.