Czy kiedykolwiek musiałeś używać przesunięcia bitów w prawdziwych projektach?


84

Czy kiedykolwiek musiałeś używać przesunięcia bitów w prawdziwych projektach programistycznych? Większość (jeśli nie wszystkie) języków wysokiego poziomu ma w sobie operatory zmiany, ale kiedy właściwie miałbyś ich używać?

Odpowiedzi:


58

Nadal piszę kod dla systemów, które nie mają sprzętowej obsługi zmiennoprzecinkowej. W tych systemach potrzebujesz przesuwania bitów dla prawie wszystkich działań arytmetycznych.

Do generowania skrótów potrzebne są również zmiany. Arytmetyka wielomianowa (CRC, kody Reeda-Solomona to główne aplikacje) lub również wykorzystuje przesunięcia.

Jednak zmiany są używane tylko dlatego, że są przydatne i wyrażają dokładnie to, co zamierzał autor. Jeśli chcesz, możesz emulować wszystkie przesunięcia bitowe z mnożeniem, ale byłoby to trudniejsze do napisania, mniej czytelne, a czasem wolniejsze.

Kompilatory wykrywają przypadki, w których mnożenie można zredukować do przesunięcia.


37

Tak, korzystałem z nich wiele razy. Skręcanie bitów jest ważne w przypadku sprzętu wbudowanego, w którym maski bitowe są bardzo powszechne. Jest to również ważne w programowaniu gier, kiedy potrzebujesz wszystkiego do końca.

Edycja: Używam ich również często do manipulowania bitmapami, na przykład do zmiany głębi kolorów lub konwersji RGB <-> BGR.


Oddelegowany. Robię dużo programowania osadzonego, a przesuwanie bitów to powszechna operacja.
James

Konwersje RGB <-> BGR tutaj.
Neil N

26
  • Tworzenie ładnych wartości flag dla wyliczeń (zamiast ręcznego wpisywania 1, 2, 4 ...)
  • Rozpakowywanie danych z pól bitowych (używa ich wiele protokołów sieciowych)
  • Przechodzenie po krzywej Z.
  • Hacki dotyczące wydajności

I nie przychodzi mi do głowy wiele przypadków, gdy są używane. Zwykle jest na odwrót - jest jakiś specyficzny problem i okazuje się, że zastosowanie operacji bitowych da najlepsze rezultaty (zwykle w zakresie wydajności - czasu i / lub przestrzeni).


Może być potrzebne do przechowywania na przykład dwóch shorts w jednym intpolu eger w stanie Sesja w ASP.net bez obciążenia związanego z odczytem i zablokowaniem sesji w celu odczytania dwóch oddzielnych wartości. Zapisywany jest również narzut pamięci związany z przechowywaniem dwóch wartości w sesji.
David d C e Freitas,

15

Jednym miejscem, w którym używam ich cały czas, jest transpozycja endian-ności liczb całkowitych dla aplikacji wieloplatformowych. Czasami przydają się również (wraz z innymi operatorami do manipulacji bitami) podczas blendowania grafiki 2D.


Po drugie, napisanie konwertera dla zestawu znaków EBCDIC. Niestety jest to naprawdę praca na niskim poziomie w języku wysokiego poziomu, ale w niektórych przypadkach jest to konieczne.
Michael Meadows


7

Nieco przesunięcia są szybkie. Zostały zaimplementowane w zestawach instrukcji procesora na długo przed operacjami dzielenia i modułu. Wielu z nas używa przesunięć bitowych do arytmetyki, która jest prosta na ołówku i papierze, ale niedostępna na naszych procesorach.

Na przykład:

  • Używałem przesunięć bitowych w projektach polegających na rozkładaniu dużych kompozytów na czynniki pierwsze.
  • Użyłem również przesunięć bitowych do znalezienia pierwiastka kwadratowego i sześciennego dowolnie dużych liczb całkowitych.

czy możesz opublikować przykład, w jaki sposób używasz go do znalezienia sześcianu lub pierwiastka kwadratowego? trochę nie rozumiem, jak można to zrobić.
Xsmael

5

Tak, nadal jest potrzebne.

W mojej pracy na przykład tworzymy oprogramowanie do komunikacji ze sterownikiem PLC poprzez port szeregowy COMx. Konieczne jest obsługiwanie bitów w bajcie, używamy przesunięcia w lewo / w prawo i operatorów logicznych OR, XOR, AND w dzień po dniu.

Na przykład załóżmy, że musimy włączyć bit 3 (od prawej do lewej) bajtu:

O wiele bardziej wydajne jest:

Byte B;

B := B XOR 4;

Zamiast:

Byte B = 0;
String s;  // 0 based index

s = ConvertToBinary (B);
s[5] = "1";
B := ConvertToDecimal (s);

Pozdrowienia.


1
Możesz chcieć dodać, dlaczego 4 odnosi się do bitu 3 (od prawej do lewej)
HCP

1
Dlaczego s [5]? Czy nie powinno to być S [2]?
IamIC,

1
B: = B XOR 4; W tym przypadku, aby włączyć określony bit, czy nie powinien to być po prostu LUB? Czy XOR nie jest używany do przełączania? stackoverflow.com/questions/47981/…
Hari

4

Kiedy pisałem w asemblerze, mój kod był pełen przesuwania bitów i maskowania.

Zrobiłem to również w C.

Nie zrobiłem tego zbyt wiele w języku JavaScript lub językach serwera.

Prawdopodobnie najlepszym współczesnym zastosowaniem jest przejście przez upakowaną tablicę wartości logicznych reprezentowanych jako jedynki i zera. Kiedyś zawsze przesuwałem w lewo i sprawdzałem bit znaku w asemblerze, ale w językach wyższego poziomu porównujesz z wartością.

Na przykład, jeśli masz 8 bitów, zaznacz górny bit za pomocą „if (a> 127) {...}”. Następnie w lewo shift (lub pomnóż przez 2), wykonaj "i" z 127 (lub odejmij 256, jeśli ostatni bit został ustawiony) i zrób to ponownie.


3

Używałem ich często w kompresji / dekompresji obrazu, gdzie bity w mapie bitowej były kompresowane. Korzystając z http://en.wikipedia.org/wiki/Huffman_coding , kompresowane elementy składają się z różnych liczb bitów (nie wszystkie są wyrównane do bajtów), dlatego trzeba je przesuwać podczas kodowania lub dekodowania .


3

Na przykład w implementacji metod kryptograficznych w językach takich jak C, C ++. Pliki binarne, algorytmy kompresji i operacje na listach logicznych - operacja bitowa jest zawsze dobra =)


3

Przesuwanie bitów nie rozwiązuje problemów programowania wysokiego poziomu, ale po prostu czasami musimy rozwiązywać problemy niższego poziomu i wygodnie jest nie pisać osobnej biblioteki w C, aby to zrobić. Domyślam się, że wtedy jest używany najczęściej.

Osobiście użyłem go do napisania kodera dla konwertera zestawu znaków EBCDIC .


3

Tak, mam. Jak można się domyślać, najprawdopodobniej można to znaleźć w programowaniu niskopoziomowym, na przykład przy opracowywaniu sterowników urządzeń. Ale pracowałem nad projektem C #, w którym musiałem opracować usługę internetową, która odbierała dane z urządzeń medycznych. Wszystkie dane binarne przechowywane przez urządzenie zostały zakodowane w pakietach SOAP, ale dane binarne zostały skompresowane i zakodowane. Aby go zdekompresować, musiałbyś wykonać wiele operacji bitowych. Co więcej, musiałbyś dużo przesuwać bitów, aby przeanalizować wszelkie przydatne informacje, na przykład numer seryjny urządzenia to dolna połowa drugiego bajtu lub coś w tym rodzaju. Widziałem też ludzi ze świata .NET (C #), którzy używają maskowania bitów i atrybutu flagi, osobiście nigdy nie miałem takiej ochoty.


3

tak. Muszę wcześniej napisać algorytmy szyfrowania i to zdecydowanie ich używa.

Są również przydatne podczas używania liczb całkowitych itp. Do śledzenia statusów.



3

Pracuję dla producenta urządzeń peryferyjnych. Spotkałem się i musiałem implementować kod, który używa przesunięć bitowych, prawie codziennie.


3

Przesuwanie bitów jest często używane do rozszyfrowania protokołów gier online. Protokoły są zaprojektowane tak, aby wykorzystywać możliwie jak najmniejsze pasmo, więc zamiast przesyłać liczbę graczy na serwerze, imiona i tak dalej w int32, wszystkie informacje są pakowane do jak najmniejszej liczby bajtów. W dzisiejszych czasach nie jest to naprawdę konieczne, ponieważ większość ludzi korzysta z łączy szerokopasmowych, ale kiedy zostały pierwotnie zaprojektowane, do gier używano modemów 56k, więc liczył się każdy bit.

Najbardziej znanymi tego przykładami są gry wieloosobowe Valve, w szczególności Counter-Strike, Counter-Strike Source. Protokół Quake3 jest również taki sam, jednak Unreal nie jest tak szczupły.

Oto przykład (.NET 1.1)

string data = Encoding.Default.GetString(receive);

if ( data != "" )
{
    // If first byte is 254 then we have multiple packets
    if ( (byte) data[0] == 254 )
    {
        // High order contains count, low order index
        packetCount = ((byte) data[8]) & 15; // indexed from 0
        packetIndex = ((byte) data[8]) >> 4;
        packetCount -= 1;

        packets[packetIndex] = data.Remove(0,9);
    }
    else
    {
        packets[0] = data;

    }
}

Oczywiście, czy postrzegasz to jako prawdziwy projekt, czy tylko hobby (w C #), zależy od Ciebie.



2

Znajdź najbliższą potęgę dwóch większych lub równych podanej liczbie:

1 << (int)(ceil(log2(given)))

Potrzebne do teksturowania na sprzęcie, który nie obsługuje dowolnych rozmiarów tekstur.


2

Inną bardzo powszechną rzeczą jest wykonanie 4-bitowego przesunięcia podczas wyodrębniania wysokiego półbajtu bajtu, tj

#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte)  ( (byte)       & 0x0F)

Jest to szczególnie ważne, jeśli pracujesz bezpośrednio ze sprzętem, pobierając dane bezpośrednio z rejestrów z dowolnym mapowaniem bitów.
Chris

1

Tak, użyłem ich w parserze strumienia MPEG2-2 Transport. Było łatwiejsze i bardziej czytelne.


1

Musiałem napisać program do analizowania plików .ifo na dyskach DVD. Są to pola, które wyjaśniają, ile tytułów, rozdziałów, menu itp. Znajduje się na płycie. Składają się z zapakowanych bitów o różnych rozmiarach i ułożeniach. Podejrzewam, że wiele formatów binarnych wymaga podobnego przesunięcia bitów.


1

Widziałem operatory bitowe używane, gdy jako parametr właściwości użyto wielu flag. Na przykład liczba 4 = 1 0 0 oznacza, że ​​ustawiona jest jedna z trzech flag. Nie jest to dobre dla publicznego interfejsu API, ale może przyspieszyć działanie w szczególnych przypadkach, ponieważ sprawdzanie bitów jest szybkie.


1

Każdy bitblt-er, który kiedykolwiek napisałem, nie mógł zostać ukończony bez możliwości przesuwania bitów w lewo i prawo.


1

Używałem ich w grach do pakowania kilku flag w jeden bajt / znak w celu zapisania na karcie danych. Rzeczy takie jak przechowywanie statusu elementów do odblokowania itp. Nie jest to obecnie wymagane, ale może zaoszczędzić pracę.


1

Używam go w projekcie dla systemu wbudowanego, który musi odczytywać dane EDID monitora. Niektóre dane w EDID są zakodowane w następujący sposób:

Bajt 3:
Wygaszanie poziome - dolne 8 bitów
Bajt 4:
Dolny półbajt: Wygaszanie poziome - górne 4 bity
Górny półbajt: coś innego

1

Tak, podczas wykonywania komunikacji binarnej między aplikacjami Java i C #, jedna to kolejność bajtów typu big-endian, a druga to little-endian (niekoniecznie w tej kolejności). Stworzyłem klasę InputStream, która mogła odczytywać liczby z inną kolejnością bajtów i korzystała z przesuwania bajtów, aby działać.

Czasami również, gdy chcesz umieścić 4 zwarcia w 4 bajtach długości, może to być przypadek użycia przesuwania bajtów. Myślę, że zrobiłem to wiele lat temu ...


0

Przesunięcie bitu jest również wymagane w przypadku komunikacji z urządzeniami „niższego poziomu”, np. Cyfrowymi skrzynkami IO-Box Ethernet Ethernet lub PLC, które zwykle pakują pozostałe wartości wejścia / wyjścia w bajty.



0

Tak, cały czas. Podobnie jak te makra do pakowania i rozpakowywania współrzędnych 3-spacji do / z 32-bitowej liczby całkowitej:

#define Top_Code(a, b, c)           ((((a) + x) << 20) | (((b) + y) << 10) | ((c) + z))                           
#define From_Top_Code(a, b, c, f)   (a = (((f) >>> 20) - x), b = ((((f) & 0xffc00) >>> 10) - y), c = (((f) & 0x3ff) - z))        

0

Kiedyś (wiele, wiele lat temu) napisałem procedurę wyjściową dla projektu, który tworzył arkusze kalkulacyjne Excel przy użyciu struktury Excel Oper. Był to format pliku binarnego, który wymagał dużej ilości manipulowania bitami. Poniższy link daje pogląd na strukturę Oper Safari Books .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.