Вот фрагмент кода:Javascript сдвиг вправо отрицательное число
var i = 101;
console.log('101: ' + i.toString(2));
console.log('101 >> 1: ' + (i >> 1).toString(2));
var l = -101;
console.log('-101: ' + l.toString(2));
console.log('-101 >> 1: ' + (l >> 1).toString(2));'
Выход:
"101: 1100101"
"101 >> 1: 110010"
"-101: -1100101"
"-101 >> 1: -110011"
Почему -101 >> 1
является -110011
вместо -110010
?
Обновление: книга Профессиональный JavaScript для веб-разработчиков объясняет, как JS сохраняет отрицательное число:
- получить двоичное представление абсолютной величины отрицательного числа
- заменить 0s с 1 с и 1 с 0 с
- добавить 1 к результату этапа 2
Так что в моем случае -101 >> 1
, мы сначала преобразовать -101 в его двоичном представлении:
Двоичное представление Math.abs (-101) является:
инвертировать 0s и 1s:
1111 1111 1111 1111 1111 1111 1010 тысяча один
добавить 1 к концу:
Теперь сдвиг вправо на 1:
Бинарный код должен быть правильным результатом -101 >> 1
, но при регистрации двоичного представления отрицательного числа Javascript просто помещает отрицательный знак перед двоичным представлением положительного числа:
var x = 15;
console.log(x.toString(2)); // output: 1111
var y = -15;
console.log(y.toString(2)); // output: -1111
В нашем примере это означает, что при входе результат -101 >> 1
, JS будет выводить minus sign
+ the binary representation of the positive number
.Но положительное число не 101 >> 1
, потому что 101 >> 1
дает:
(101 >> 1).toString(2); // output: 110010
(-101 >> 1).toString(2); // output: -110011, not -110010!
Чтобы получить правильный результат, мы должны обратить вышеупомянутый шаг 1-3:
1111 1111 1111 1111 1111 1111 1100 1101 // this is the result we get from step 4
Обратный шаг 3 путем вычитания 1, мы получаем:
1111 1111 1111 1111 1111 1111 1100 1100
Обратный шаг 2 по инвертных 0 и 1:
0000 0000 0000 0000 0000 0000 0011 0011
Обратный шаг 1 путем преобразования этого двоичного файла в целое:
parseInt(110011, 2); // output: 51
Наконец, когда JS записывает результат -101 >> 1
, это будет minus sign
+ the binary representation of 51
который:
(51).toString(2); // output: 110011
(-101 >> 1).toString(2); // output: -110011
'>>' (сдвиг вправо) - ** Этот оператор сдвигает первый операнд на указанное количество бит вправо. Избытые биты, сдвинутые вправо, отбрасываются. Копии самого левого бита сдвигаются слева. Поскольку новый левый бит имеет то же значение, что и предыдущий самый левый бит, бит знака (самый левый бит) не изменяется. Отсюда и название «знак распространения». ** – evolutionxbox