Відповіді:
>>- це арифметичний зсув праворуч, >>>логічний зсув праворуч.
У арифметичному зсуві бітовий знак розширюється для збереження підписаності числа.
Наприклад: -2, представлені у 8 бітах, було б 11111110(оскільки найзначніший біт має негативну вагу). Переміщення його правою біткою за допомогою арифметичного зсуву дасть вам 11111111або -1. Однак, логічний зсув праворуч не хвилює, що значення може представляти підписане число; він просто переміщує все праворуч і заповнює зліва на 0. Зміщення нашого -2 правого біта за допомогою логічного зсуву дасть би 01111111.
2^k, я вважаю дивним, що це відповідь кожного. Рядок бітів не є числом і >>завжди може бути використаний для будь-якого рядка бітів: він завжди виконує те саме, незалежно від ролі, яку грає рядок бітів, і незалежно від того, чи має вона поняття "знак". Чи було б добре поширити свою вже чудову відповідь обговоренням випадку, коли ваш операнд не трактується як підписаний номер? Чи має сенс моя скарга?
Stringможе також розглядатися як a char[]. Він не каже, що а char- це не число; він просто каже, що це непідписаний номер. Я думаю, саме там він загубився.
>>>є беззнаковою зміною; він вставить 0. >>підписано, і розширить біт знака.
Оператори зміни включають ліву зміну
<<, підписану праву зміну>>та неподписану праву зміну>>>.Значення
n>>sєnправою зсунутіsбітові позиції з знаком-розширення .Значення
n>>>sєnправою зсунутіsбітові позиції з нульовим розширенням .
System.out.println(Integer.toBinaryString(-1));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >> 16));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >>> 16));
// prints "1111111111111111"
Щоб зробити речі більш чіткими, додайте позитивний аналог
System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"
Оскільки він є позитивним, і підписані, і неподписані зрушення додадуть 0 до лівого самого біта.
1 >>> 32 == 1Вони обидва зсуву вправо, але >>>єunsigned
З документації :
Оператор непідписаного правого зсуву ">>>" зміщує нуль у крайнє ліве положення, тоді як крайнє ліве положення після ">>" залежить від розширення знака.
>>>це не підписано, але чому це так 7>>32=7? Я пробіг цикл, який робив одну зміну за часом, і побачив, що після 32змін він повернувся до 7. Єдиний спосіб, що це може мати сенс, це те, що для кожного зміщеного числа воно входило в "зовнішнє коло". Після 32зрушень вона якось повернулася до своєї позиції, але очевидно, що все ще не має сенсу. Що відбувається?
Логічний правий зсув ( v >>> n) повертає значення, в якому біти vзміщені вправо nбітовими позиціями, а 0-і зміщені з лівого боку. Розглянемо зміщення 8-бітних значень, записаних у двійковій формі:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
Якщо ми інтерпретуємо біти як непідписане невід'ємне ціле число, логічний правильний зсув має наслідком ділення числа на відповідну потужність 2. Однак, якщо число є в представленні двох доповненнях, логічний правий зсув неправильно розділяє від'ємні числа . Наприклад, другий правий зсув вище зміщується 128 на 32, коли біти інтерпретуються як непідписані числа. Але вона зміщується від -128 до 32, коли, як це характерно для Java, біти інтерпретуються в доповнення двох.
Тому, якщо ви зміщуєтесь, щоб ділити на потужність дві, вам потрібно арифметичний правий зсув ( v >> n). Він повертає значення, в якому біти vзміщені вправо по nбітових позиціях, а копії самого лівого біта v зміщуються з лівого боку:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
Коли біти є числом у поданні доповнення двох, арифметичний правий зсув має ефект ділення на потужність двох. Це працює, тому що крайній лівий біт є бітовим знаком. Ділення на потужність двох повинно зберігати знак однаковим.
Детальніше про операцій з побітним розрядом та зсувом біт
>> Signed right shift
>>> Unsigned right shift
Бітова схема задається лівим операндом, а кількість позицій, що зміщуються правою операндом. Оператор безпідписаного правого зсуву >>> зміщує нуль у крайнє ліве положення ,
тоді як крайнє ліве положення після >>залежить від розширення знака.
Простими словами >>>завжди зміщується нуль у крайньому лівому положенні, тоді як >>зміщується на основі знака числа, тобто 1 для від’ємного числа та 0 для додатного числа.
Наприклад, спробуйте як з негативними, так і з додатними числами.
int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));
System.out.println();
c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
вихід:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')); Integer.MAX_VALUE : 01111111111111111111111111111111; Integer.MIN_VALUE : 10000000000000000000000000000000; -1 : 11111111111111111111111111111111; 0 : 00000000000000000000000000000000; 1 : 00000000000000000000000000000001
Логічний оператор зсуву правого зсуву ( >>> N) зміщує біти вправо на N позицій, відкидаючи біт знаків і додаючи N більшості лівих бітів 0. Наприклад:
-1 (in 32-bit): 11111111111111111111111111111111
після >>> 1операції стає:
2147483647: 01111111111111111111111111111111
Арифметичний оператор правого зсуву ( >> N) також зміщує біти вправо на N позицій, але зберігає біт знаків і прошиває N найбільш білих лівих на 1. Наприклад:
-2 (in 32-bit): 11111111111111111111111111111110
після >> 1операції стає:
-1: 11111111111111111111111111111111