Вязовик Н.А.
Шрифт:
При сдвиге влево оператором << все биты числа смещаются на указанное количество позиций влево, причем освободившиеся справа позиции заполняются нулями. Эта операция аналогична умножению на 2n и действует вполне предсказуемо, как при положительных, так и при отрицательных аргументах.
Рассмотрим примеры применения операторов сдвига для значений типа int, т.е. 32-битных чисел. Пусть положительным аргументом будет число 20, а отрицательным -21.
// Сдвиг влево для положительного числа 20
20 << 00 = 00000000000000000000000000010100 = 20
20 << 01 = 00000000000000000000000000101000 = 40
20 << 02 = 00000000000000000000000001010000 = 80
20 << 03 = 00000000000000000000000010100000 = 160
20 << 04 = 00000000000000000000000101000000 = 320
...
20 << 25 = 00101000000000000000000000000000 = 671088640
20 << 26 = 01010000000000000000000000000000 = 1342177280
20 << 27 = 10100000000000000000000000000000 = -1610612736
20 << 28 = 01000000000000000000000000000000 = 1073741824
20 << 29 = 10000000000000000000000000000000 = -2147483648
20 << 30 = 00000000000000000000000000000000 = 0
20 << 31 = 00000000000000000000000000000000 = 0
// Сдвиг влево для отрицательного числа -21
– 21 << 00 = 11111111111111111111111111101011 = -21
– 21 << 01 = 11111111111111111111111111010110 = -42
– 21 << 02 = 11111111111111111111111110101100 = -84
– 21 << 03 = 11111111111111111111111101011000 = -168
– 21 << 04 = 11111111111111111111111010110000 = -336
– 21 << 05 = 11111111111111111111110101100000 = -672
...
– 21 << 25 = 11010110000000000000000000000000 = -704643072
– 21 << 26 = 10101100000000000000000000000000 = -1409286144
– 21 << 27 = 01011000000000000000000000000000 = 1476395008
– 21 << 28 = 10110000000000000000000000000000 = -1342177280
– 21 << 29 = 01100000000000000000000000000000 = 1610612736
– 21 << 30 = 11000000000000000000000000000000 = -1073741824
– 21 << 31 = 10000000000000000000000000000000 = -2147483648
Как видно из примера, неожиданности возникают тогда, когда значащие биты начинают занимать первую позицию и влиять на знак результата.
При сдвиге вправо все биты аргумента смещаются на указанное количество позиций, соответственно, вправо. Однако встает вопрос – каким значением заполнять освобождающиеся позиции слева, в том числе и отвечающую за знак. Есть два варианта. Оператор >> использует для заполнения этих позиций значение знакового бита, то есть результат всегда имеет тот же знак, что и начальное значение. Второй оператор >>> заполняет их нулями, то есть результат всегда положительный.
// Сдвиг вправо для положительного числа 20
// Оператор >>
20 >> 00 = 00000000000000000000000000010100 = 20
20 >> 01 = 00000000000000000000000000001010 = 10
20 >> 02 = 00000000000000000000000000000101 = 5
20 >> 03 = 00000000000000000000000000000010 = 2
20 >> 04 = 00000000000000000000000000000001 = 1
20 >> 05 = 00000000000000000000000000000000 = 0
// Оператор >>>
20 >>> 00 = 00000000000000000000000000010100 = 20
20 >>> 01 = 00000000000000000000000000001010 = 10
20 >>> 02 = 00000000000000000000000000000101 = 5
20 >>> 03 = 00000000000000000000000000000010 = 2
20 >>> 04 = 00000000000000000000000000000001 = 1
20 >>> 05 = 00000000000000000000000000000000 = 0
Очевидно, что для положительного аргумента операторы >> и >>> работают совершенно одинаково. Дальнейший сдвиг на большее количество позиций будет также давать нулевой результат.
// Сдвиг вправо для отрицательного числа -21
// Оператор >>
– 21 >> 00 = 11111111111111111111111111101011 = -21
– 21 >> 01 = 11111111111111111111111111110101 = -11
– 21 >> 02 = 11111111111111111111111111111010 = -6
– 21 >> 03 = 11111111111111111111111111111101 = -3
– 21 >> 04 = 11111111111111111111111111111110 = -2
– 21 >> 05 = 11111111111111111111111111111111 = -1
// Оператор >>>