2012-10-02 20 views
12

Sto leggendo alcuni valori da un singolo byte. Nel manuale utente mi è stato detto che questo byte contiene 3 valori diversi. C'è un tavolo che assomiglia a questo:C#, bit e byte - Come posso recuperare i valori di bit da un byte?

bit table

interpreto che la precisione ha un senso prende 3 bit, scala prende 2 e le dimensioni occupa 3 per un totale di 8 (1 byte).

Quello che non sono chiare su è:

1 - Perché è etichettato da 7 a 0, invece di 0 a 7 (qualcosa a che fare con un significato forse?)

2 - Come posso estrarre i singoli valori fuori da quell'unico byte?

risposta

17

è d'uso numerare i bit in un byte in base al loro significato: il bit x rappresenta 2^x. Secondo questo schema di numerazione, il bit meno significativo ottiene il numero zero, il bit successivo è il numero uno e così via.

Ottenere singoli bit richiede un cambiamento e di un'operazione di mascheramento:

var size = (v >> 0) & 7; 
var scale = (v >> 3) & 3; 
var precision = (v >> 5) & 7; 

Maiusc per il numero di bit alla destra della parte più a destra che è necessario per ottenere (spostando per zero viene ignorato, ho aggiunto a scopo illustrativo).

Maschera con il numero più alto che si adatta al numero di bit che si desidera ottenere: 1 per un bit, 3 per due bit, 7 per tre bit, 2^x-1 per x bit.

+0

Grazie per la spiegazione di come funziona anche il numero di maschera. – bugfixr

+0

Prova gli operatori nell'altro modo in cui rond: var size = ((v & 7) >> 0); var scale = ((v & 28) >> 3); var precision = ((v & 224) >> 5); – Robetto

3

1. Sì, il bit più significativo viene solitamente scritto per primo. Il bit più a sinistra è etichettato 7 perché quando il byte viene interpretato come un numero intero, quel bit ha valore 2 (= 128) quando è impostato.

Questo è completamente naturale ed è in effetti esattamente lo stesso di come si scrivono i numeri decimali (prima la cifra più significativa). Ad esempio, il numero 356 è (3 x 10 ) + (5 x 10 ) + (6 x 10 ).

2. Per il completamento, come detto in altre risposte è possibile estrarre i singoli valori usando lo spostamento bit e bit per bit, e gli operatori come segue:

int size = x & 7; 
int scale = (x >> 3) & 3; 
int precision = (x >> 5) & 7; 

Nota importante: questo presuppone che i valori individuali devono essere interpretato come numeri interi positivi. Se i valori potrebbero essere negativi, questo non funzionerà correttamente. Dati i nomi delle tue variabili, è improbabile che questo sia un problema qui.

+0

Ognuno di noi rispondemmo diversa metà della domanda. Abbiamo diviso un upvote o qualcosa del genere? : D – Wug

4
  1. Potayto, potahto.

  2. usereste turni e maschere di appiattire i bit indesiderati, come ad esempio:

    byte b = something; // b is our byte 
    
    int size = b & 0x7; 
    int scale = (b >> 3) & 0x3; 
    int position = (b >> 5) & 0x7; 
    
1

È possibile farlo tramite bit a bit aritmetica:

uint precision = (thatByte & 0xe0) >> 5, 
    scale = (thatByte & 0x18) >> 3, 
    size = thatByte & 7; 
6

Si può fare turni e maschere, oppure è possibile utilizzare la classe BitArray: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

Esempio con BitVector32:

BitVector32 bv = new BitVector32(0); 

var size = BitVector32.CreateSection(7); 
var scale = BitVector32.CreateSection(3, size); 
var precision = BitVector32.CreateSection(7, scale); 

bv[size] = 5; 
bv[scale] = 2; 
bv[precision] = 4; 

uscita LINQPad:

LINQPad output

+0

+1 per indicare un'alternativa che non risponde ai giorni di C: P [BitVector32] (http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx) è un'altra opzione, che ti permette anche di dividere il tuo bitfield in sezioni (corrispondenti alle dimensioni, alla scala e alla precisione dell'OP) e assegnarle o leggerle direttamente usando la sintassi dell'indicizzazione. – shambulator

+0

Questa è una risposta di collegamento. – Wug

Problemi correlati