Изменения

Перейти к: навигация, поиск

Побитовые операции

3717 байт добавлено, 19:28, 6 марта 2016
Побитовые сдвиги
C++ Visual Studio 15
Если выполняется сдвиг влево числа со знаком и при этом затрагивается бит знака, результат не определен. Результат сдвига вправо отрицательного числа со знаком зависит от реализации компилятора. Результат операции сдвига не определен, если число, на которое пользователь хочет сдвинуть биты имеет отрицательное значение или если оно больше или равно количеству битов в исходном числе.
<code>
#include <iostream>
cout << bitset4 << endl; // 000000000000000
}
</code>
 
В языке программирования Java существует также оператор беззнакового битового сдвига вправо <tex>>>></tex>. При использовании этого оператора на освободившиеся позиции всегда устанавливаются <tex>0</tex>, тогда как при использовании <tex>>></tex> на освободившиеся позиции устанавливается бит знака.
При использовании битовых сдвигов есть некоторое отличие от целочисленного деления на <tex>2</tex>: если сдвигать отрицательное число вправо, то сначала это аналогично целочисленному делению на <tex>2</tex>, но когда останется <tex>-1</tex>, то при следующих сдвигах результат меняться не будет. То есть происходит округление не к нулю, как при целочисленном делении, а к <tex>-1</tex>.
 
Нельзя сдвинуть число на количество бит большее, чем разрядность операнда. При этом происходит неявное сокращение правого (кол-во бит) операнда.
 
Примеры:
 
<code>
i 00000000000000000000000000000001 (1) <br/>
i<<29 00100000000000000000000000000000 (536870912) <br/>
i<<30 01000000000000000000000000000000 (1073741824) <br/>
i<<31 10000000000000000000000000000000 (-2147483648/2147483648) <br/>
i<<32 00000000000000000000000000000001 (1)
</code>
<code>
i 11111111111111111111111111111111 (-1/4294967295) <br/>
i>>>1 01111111111111111111111111111111 (2147483647) <br/>
i>>>30 00000000000000000000000000000011 (3) <br/>
i>>>31 00000000000000000000000000000001 (1) <br/>
i>>>32 11111111111111111111111111111111 (-1/4294967295)
</code>
<code>
i 11111111111111111111111101000000 (-192/4294967104) <br/>
i>>1 11111111111111111111111110100000 (-96/4294967200) <br/>
i>>30 11111111111111111111111111111111 (-1/4294967295) <br/>
i>>31 11111111111111111111111111111111 (-1/4294967295) <br/>
i>>32 11111111111111111111111101000000 (-192/4294967104)
</code>
 
Арифметическое распространение в Java проводится перед операциями и гарантирует расширение каждого операнда по крайней мере до int. Если же один из операндов long, то до long. Если сдвигаемая переменная по разрядности меньше, то результат будет не таким, как ожидалось. При приведении типов при расширении разрядности расширение происходит знаково. При сжатии разрядности просто отбрасываются лишние байты.
 
Примеры:
 
<code>
byte b = -127; <br/>
b 10000001 (-127/129) <br/>
(int)b 11111111 11111111 11111111 10000001 (-127/4294967169) <br/>
int i = -127; <br/>
i 11111111 11111111 11111111 10000001 (-127/4294967169) <br/>
(byte)i 10000001 (-127/129) <br/>
int i = 128; <br/>
i 00000000 00000000 00000000 10000000 (128) <br/>
(byte)i 10000000 (-128/128) <br/>
int i = 256; <br/>
i 00000000 00000000 00000001 00000000 (256) <br/>
(byte)i 00000000 (0) <br/>
int i = -256; <br/>
i 11111111 11111111 11111111 00000000 (-256/4294967040) <br/>
(byte)i 00000000 (0) <br/>
</code>
276
правок

Навигация