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ć?
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:
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.
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.
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).
short
s w jednym int
polu 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.
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.
Użyłem ich kilka razy, ale prawie zawsze do analizowania formatu pliku binarnego.
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:
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.
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.
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 .
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 .
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.
Podczas konwersji liczb z formatu little endian na format big endian i odwrotnie
Pracuję dla producenta urządzeń peryferyjnych. Spotkałem się i musiałem implementować kod, który używa przesunięć bitowych, prawie codziennie.
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.
Szybka transformata Fouriera - FFT i jej technika Cooleya-Tukeya będą wymagały użycia operacji przesunięcia bitów.
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)
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.
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.
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.
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
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 ...
Tak, przesuwanie bitów jest używane przez cały czas w oprogramowaniu wbudowanym niskiego poziomu. Może być również używany jako niemal magiczna sztuczka do wykonywania niezwykle szybkich operacji matematycznych
http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/
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))
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 .