2012-10-02 20 views
12

Czytam niektóre wartości z jednego bajtu. W podręczniku użytkownika powiedziano mi, że ten jeden bajt zawiera 3 różne wartości. Jest to tabela, która wygląda następująco:C#, bits & bytes - Jak pobrać wartości bitów z bajtu?

bit table

interpretować, że ma sens precyzja zajmuje 3 bity, skala zajmuje 2 i wielkości zajmuje 3 w sumie 8 (1 bajt).

Co oczywiste, nie jestem na to:

1 - Dlaczego jest to oznaczone 7 do 0 zamiast 0 do 7 (coś zrobić ze znaczeniem może?)

2 - Jak mogę wyodrębnić poszczególne wartości z tego jednego bajtu?

Odpowiedz

17

Jest zwyczajem do liczby bitów w bajcie zgodnie z ich znaczeniem: bit x reprezentuje 2^x. Zgodnie z tym schematem numeracji najmniej znaczący bit otrzymuje liczbę zero, następny bit jest numerem jeden i tak dalej.

Pierwsze poszczególnych bitów wymaga zmiany i operacji maskowania:

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

przesunięcie o liczbę bitów po prawej skrajnej prawej części, które trzeba uzyskać (przesuwanie przez zero jest ignorowana; dodałem go w celach ilustracyjnych).

Maska o najwyższej liczbie, która pasuje do liczby bitów, które chcesz uzyskać: 1 na jeden bit, 3 na dwa bity, 7 na trzy bity, 2^x-1 dla bitów x.

+0

Dzięki za wyjaśnienie, jak działa numer maski. – bugfixr

+0

Wypróbuj operatorów w inny sposób rond: var size = ((v & 7) >> 0); var scale = ((v & 28) >> 3); var precision = ((v & 224) >> 5); – Robetto

3

1. Tak, najbardziej znaczący bit jest zwykle zapisywany jako pierwszy. Najbardziej lewy bit jest oznaczony jako 7, ponieważ gdy bajt jest interpretowany jako liczba całkowita, ten bit ma wartość 2 (= 128), gdy jest ustawiony.

Jest to całkowicie naturalne i w rzeczywistości jest dokładnie takie samo jak sposób zapisywania liczb dziesiętnych (najpierw znacząca cyfra). Na przykład, liczba 356 oznacza (3 x 10 ) + (5 x 10 ) + (6 x 10 ).

2. Na zakończenie, jak wspomniano w innych odpowiedzi można wyodrębnić poszczególne wartości stosując przesunięcie bitów i bitowym i operatorów, co następuje:

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

Ważna uwaga: ta zakłada, że ​​poszczególne wartości mają być interpretowane jako dodatnich liczb całkowitych. Jeśli wartości mogą być ujemne, to nie będzie działać poprawnie. Biorąc pod uwagę nazwy zmiennych, jest to mało prawdopodobne, aby stanowiło to problem.

+0

Każdy odpowiedział inny połówki pytania. Czy podzielimy przegraną lub coś takiego? : D – Wug

4
  1. Potayto, potahto.

  2. byłoby użyć przesunięcia i maski, aby wyrównać niepożądanych bitów, takich jak:

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

Można to zrobić poprzez mnożenie arytmetyki:

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

można robić zmiany i maski, czy można użyć klasy BitArray: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

Przykład z 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; 

wyjście LINQPad:

LINQPad output

+0

+1 za wskazanie alternatywy, która nie przywraca dni C: P [BitVector32] (http://msdn.microsoft.com/en-us/library/system.collections.specialized.bitvector32.aspx) to kolejna opcja, która pozwala również na podzielenie twojego pola bitowego na sekcje (odpowiadające rozmiarowi, skali i dokładności OP) i przypisanie lub odczytanie każdego z nich bezpośrednio za pomocą składni indeksującej. – shambulator

+0

To jest odpowiedź łącza. – Wug

Powiązane problemy