2009-11-06 23 views
5

Najlepszy w PHP,Jak odwrócić bity bajtu?

np

11011111 ==> 11111011

+5

dobrze, w tym przypadku obracać w prawo przez 5 pozycji: P –

+4

Twoje pytanie wymaga nieco więcej wyjaśnień. Na przykład, czy jest to ciąg lub rzeczywistą liczbę całkowitą, których bitów próbujesz odwrócić? Kontekst jest bardzo ważny, gdy zadajesz pytanie. –

+2

@klez - +1 lol, prawie kazałeś mi wypluć moją kawę na klawiaturę = P –

Odpowiedz

2

Spróbuj dostać tę książkę, jest cały rozdział o bity rewersyjną: Hacker's Delight. Ale najpierw sprawdź zawartość, jeśli ci pasuje.

8

Najszybszym sposobem, ale także wymagającym więcej miejsca, jest wyszukiwanie, w którym każda możliwa wartość bajtu (256, jeśli idziesz na cały zakres), jest powiązana z jego "odwróconym" odpowiednikiem.

Jeśli masz tylko kilka takich bajtów w obsłudze, operatorzy bitową zrobi, ale że będzie wolniejszy, może coś takiego:

function reverseBits($in) { 
    $out = 0; 

    if ($in & 0x01) $out |= 0x80; 
    if ($in & 0x02) $out |= 0x40; 
    if ($in & 0x04) $out |= 0x20; 
    if ($in & 0x08) $out |= 0x10; 
    if ($in & 0x10) $out |= 0x08; 
    if ($in & 0x20) $out |= 0x04; 
    if ($in & 0x40) $out |= 0x02; 
    if ($in & 0x80) $out |= 0x01; 

    return $out; 
} 
+0

Historycznie, odkryłem, że posiadanie 256-bajtowego tabeli odnośników to najszybszy sposób, aby to osiągnąć, ponieważ jest to tylko odnośnik. 256 bajtów nie jest dużo miejsca do poświęcenia na coś takiego, jeśli musi być szybki. Chociaż powyższa funkcja reverseBits jest tak mała i ciasna, jak tylko można uzyskać kod bez szukania. Również dla jednej małej optymalizacji możesz zmienić pierwsze {$ out | = 0x80;} na {$ out = 0x80;}, ponieważ wiesz, że po raz pierwszy jesteś ORing z 0. – skirmish

+0

@skirmish, zgodziłem się, że będę dążył do w większości przypadków używaj tablicy odnośników. Rozwiązaniem pośrednim byłoby posiadanie mniejszej tablicy dla 4 bitów i wykonanie dwóch wyszukiwań z powiązanym mnożeniem/dzieleniem dla lewego lewego kwadratu bitowego. Ten sposób działania może być również użyty do czynienia z liczbami całkowitymi, a raczej bajtami. (Minusem podejścia do wyszukiwania jest to, że jego zapotrzebowanie na przestrzeń rośnie wykładniczo, przy czym kodowane okoń liniowo (w/dotyczy liczby bitów). – mjv

18

Prosta podejście do przodu jest wykonanie 8 masek, 8 obraca i 7 dodatki:

$blah = $blah & 128 >> 7 + $blah & 64 >> 5 + $blah & 32 >> 3 + $blah & 16 >> 1 + $blah & 8 << 1 + $blah & 4 << 3 + $blah & 2 << 5 + $blah & 1 << 7; 
+1

To dostało dwie rewersy? –

+1

@Kinopiko: 3 upvotes, z moimi. lepsze rozwiązanie, opublikuj to, a dostaniesz mój głos też! – Seb

+0

Cóż, odpowiada na pytanie :-) –

14

Jeśli masz już bity w postaci ciągu znaków, należy strrev.

Jeśli nie, skonwertuj najpierw bajt na jego binarną reprezentację za pomocą decbin, a następnie odwróć za pomocą strrev, a następnie wróć do bajtu (jeśli to konieczne), używając bindec.

+1

Najlepsza odpowiedź IMO, która będzie działać w przypadkach ogólnych. Te zmiany bitów, rotacja itp. Są po prostu ukierunkowane na przykładową wartość i nie będą działać dla losowych ciągów binarnych. – Lukman

+0

+1 To jest to, co bym zasugerował, gdybym nie spartaczył wstępnego zrozumienia. –

+0

Naprawdę ciekawi mnie, dlaczego zostałem tutaj odrzucony ... – Konamiman

14

Sprawdź sekcję dotyczącą sekwencji bitów odwracających w Bit Twiddling Hacks. Powinno być łatwo dostosować jedną z technik do PHP.

Chociaż prawdopodobnie nie praktyczny dla PHP, jest szczególnie fascynująca pomocą 3 operacje 64-bitowe:

unsigned char b; // reverse this (8-bit) byte 
b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023; 
+0

Czy możesz wyjaśnić, co oznacza "ULL"? – Mask

+4

@ Maska, która jest niepodpisana długo, sufiks mówi kompilatorowi, że to, co się dzieje, to 64-bitowa liczba całkowita bez znaku. – PeterAllenWebb

+0

dlaczego jest to rozwiązanie, które nie jest praktyczne dla PHP? – denoise

1

Nie zgadzam się z użyciem zapoznać się tabelę jako (dla większych liczb całkowitych) ilość czasu niezbędnego do jej załadowania do wydajności przetwarzania atutów pamięci.

Używam również podejście bitowe maskujący o (logn) roztworu O, który wygląda następująco:

MASK = onescompliment of 0  
while SIZE is greater than 0 
    SIZE = SIZE shiftRight 1 
    MASK = MASK xor (MASK shiftLeft SIZE) 
    output = ((output shiftRight SIZE) bitwiseAnd MASK) bitwiseOR ((onescompliment of MASK) bitwiseAnd (output shfitLeft SIZE)) 

Zaletą tego podejścia jest to obsługuje rozmiaru całkowitą jako argumentu

w php to może wyglądać:

function bitrev($bitstring, $size){ 

    $mask = ~0; 
    while ($size > 0){ 

    $size = $size >> 1; 
    $mask = $mask^($mask << $size); 
    $bitstring = (($bitstring >> $size) & $mask) | ((~$mask) & ($bitstring << $size)); 
    } 
} 

chyba wkręca się moje php gdzieś :(

+0

jeśli wykonujesz operację tylko raz, tabela odnośników jest zła. Ale jeśli jest to częsta operacja, powinna przewyższać inne podejście. –

3

To jest O (n) z długością bitu. Po prostu myśl o danych wejściowych jako stosie i napisz do stosu wyjściowego.

Moja próba napisania tego w PHP.

function bitrev ($inBits, $bitlen){ 
    $cloneBits=$inBits; 
    $inBits=0; 
    $count=0; 

    while ($count < $bitlen){ 
     $count=$count+1; 
     $inBits=$inBits<<1; 
     $inBits=$inBits|($cloneBits & 0x1); 
     $cloneBits=$cloneBits>>1; 
    } 

    return $inBits; 
} 
1

Niektóre osoby zostały sugerując tabeli odnośników, a ja zostały podejmowania jedno:

[ 
     0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 
     0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 
     0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 
     0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 
     0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 
     0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 
     0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 
     0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 
     0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 
     0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 
     0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 
     0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 
     0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 
     0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 
     0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 
     0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF, 
][$byte] 

A oto wersję znaków:

[ 
    "\x00", "\x80", "\x40", "\xC0", "\x20", "\xA0", "\x60", "\xE0", "\x10", "\x90", "\x50", "\xD0", "\x30", "\xB0", "\x70", "\xF0", 
    "\x08", "\x88", "\x48", "\xC8", "\x28", "\xA8", "\x68", "\xE8", "\x18", "\x98", "\x58", "\xD8", "\x38", "\xB8", "\x78", "\xF8", 
    "\x04", "\x84", "\x44", "\xC4", "\x24", "\xA4", "\x64", "\xE4", "\x14", "\x94", "\x54", "\xD4", "\x34", "\xB4", "\x74", "\xF4", 
    "\x0C", "\x8C", "\x4C", "\xCC", "\x2C", "\xAC", "\x6C", "\xEC", "\x1C", "\x9C", "\x5C", "\xDC", "\x3C", "\xBC", "\x7C", "\xFC", 
    "\x02", "\x82", "\x42", "\xC2", "\x22", "\xA2", "\x62", "\xE2", "\x12", "\x92", "\x52", "\xD2", "\x32", "\xB2", "\x72", "\xF2", 
    "\x0A", "\x8A", "\x4A", "\xCA", "\x2A", "\xAA", "\x6A", "\xEA", "\x1A", "\x9A", "\x5A", "\xDA", "\x3A", "\xBA", "\x7A", "\xFA", 
    "\x06", "\x86", "\x46", "\xC6", "\x26", "\xA6", "\x66", "\xE6", "\x16", "\x96", "\x56", "\xD6", "\x36", "\xB6", "\x76", "\xF6", 
    "\x0E", "\x8E", "\x4E", "\xCE", "\x2E", "\xAE", "\x6E", "\xEE", "\x1E", "\x9E", "\x5E", "\xDE", "\x3E", "\xBE", "\x7E", "\xFE", 
    "\x01", "\x81", "\x41", "\xC1", "\x21", "\xA1", "\x61", "\xE1", "\x11", "\x91", "\x51", "\xD1", "\x31", "\xB1", "\x71", "\xF1", 
    "\x09", "\x89", "\x49", "\xC9", "\x29", "\xA9", "\x69", "\xE9", "\x19", "\x99", "\x59", "\xD9", "\x39", "\xB9", "\x79", "\xF9", 
    "\x05", "\x85", "\x45", "\xC5", "\x25", "\xA5", "\x65", "\xE5", "\x15", "\x95", "\x55", "\xD5", "\x35", "\xB5", "\x75", "\xF5", 
    "\x0D", "\x8D", "\x4D", "\xCD", "\x2D", "\xAD", "\x6D", "\xED", "\x1D", "\x9D", "\x5D", "\xDD", "\x3D", "\xBD", "\x7D", "\xFD", 
    "\x03", "\x83", "\x43", "\xC3", "\x23", "\xA3", "\x63", "\xE3", "\x13", "\x93", "\x53", "\xD3", "\x33", "\xB3", "\x73", "\xF3", 
    "\x0B", "\x8B", "\x4B", "\xCB", "\x2B", "\xAB", "\x6B", "\xEB", "\x1B", "\x9B", "\x5B", "\xDB", "\x3B", "\xBB", "\x7B", "\xFB", 
    "\x07", "\x87", "\x47", "\xC7", "\x27", "\xA7", "\x67", "\xE7", "\x17", "\x97", "\x57", "\xD7", "\x37", "\xB7", "\x77", "\xF7", 
    "\x0F", "\x8F", "\x4F", "\xCF", "\x2F", "\xAF", "\x6F", "\xEF", "\x1F", "\x9F", "\x5F", "\xDF", "\x3F", "\xBF", "\x7F", "\xFF", 
][ord($byte)];