BitLab vzorek, který se někdo zeptá

Tohle je statická kopie kapitoly pro vyhledávače. Interaktivní verze má animované obrázky, kontrolní otázky a tlačítka, která příklad načtou do kalkulačky.

Posuny: a ten vpravo, který má dvě odpovědi

Posun vlevo je jednoznačný. Bity se posunou, zprava nalezou nuly, a co vyleze nahoře, to je pryč. Odpovídá to násobení dvěma:

x << n = x · 2ndokud se to vejde
vstup11111000-8 / 248« 211100000× 4» 2 logicky0011111062» 2 aritmeticky11111110-2ZÁPORNÉ číslo: dvě různé odpovědi na jednu značku »
Zkus hodnotu s nastaveným nejvyšším bitem — třeba 0xF8, což je se znaménkem −8. Poslední dva řádky se pak rozejdou.

A teď doprava

Zprava se bity ztrácejí a shora něco nalézt musí. Jenže co? Existují dvě odpovědi a obě jsou správně — pro jinou otázku:

posunshora lezeje to správně pro
logický (>>>)nulavzorek bitů — masku, příznaky, surová data
aritmetický (>>)kopie znaménkového bitučíslo se znaménkem

U kladných čísel dávají obě totéž, takže se ten rozdíl nikdy neprojeví — dokud se neobjeví první záporná hodnota. Pak logický posun z −1 udělá 255.

Který z nich dostanete, není vaše volba — je to typ. V C rozhoduje, jestli je proměnná signed, nebo unsigned; ten samý zápis x >> 1 udělá dvě různé věci. V Javě a v JavaScriptu jsou to dva různé operátory, >> a >>>, což je poctivější.

Druhá polovina té pasti: zaokrouhlování

„Posun vpravo je dělení dvěma“ platí pro kladná čísla. Pro záporná ne úplně:

−7 >> 1 = −4     ale     −7 / 2 = −3dvě různé odpovědi

Aritmetický posun zaokrouhluje dolů, k mínus nekonečnu. Celočíselné dělení v C zaokrouhluje k nule. Kdo v optimalizaci nahradí / 2 za >> 1, změní chování u záporných vstupů — a překladač to sám neudělá právě proto, že by tím změnil výsledek.

Rotace

Rotace je posun, který nic neztrácí: co vyleze nahoře, naleze zdola. Je to permutace bitů — počet jedniček se nemění a po w rotacích je slovo tam, kde bylo. Používá se v kryptografii a v kontrolních součtech; běžné jazyky pro ni operátor nemají a překladač ji poskládá z dvou posunů a OR.

Posun o víc než je šířka typu je v C nedefinovaný, ne „vyjde nula“. Na x86 procesor bere jen spodních 5 bitů počtu, takže x << 32 je x << 0 — tedy x. Na ARM vyjde nula. Obojí je „správně“, protože norma neříká nic.

Vzorce v této kapitole

« — posun vlevo
x << n = x · 2ⁿ [—] kap. 7
» — aritmetický posun zaokrouhluje k −∞
−7 >> 1 = −4 ≠ −7 / 2 [—] kap. 7