2016-05-04 3 views
1

Вот фрагмент кода: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 сохраняет отрицательное число:

  1. получить двоичное представление абсолютной величины отрицательного числа
  2. заменить 0s с 1 с и 1 с 0 с
  3. добавить 1 к результату этапа 2

Так что в моем случае -101 >> 1, мы сначала преобразовать -101 в его двоичном представлении:

  1. Двоичное представление Math.abs (-101) является:

  2. инвертировать 0s и 1s:

    1111 1111 1111 1111 1111 1111 1010 тысяча один

  3. добавить 1 к концу:

  4. Теперь сдвиг вправо на 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 
+0

'>>' (сдвиг вправо) - ** Этот оператор сдвигает первый операнд на указанное количество бит вправо. Избытые биты, сдвинутые вправо, отбрасываются. Копии самого левого бита сдвигаются слева. Поскольку новый левый бит имеет то же значение, что и предыдущий самый левый бит, бит знака (самый левый бит) не изменяется. Отсюда и название «знак распространения». ** – evolutionxbox

ответ

0

Напомним, что отрицательное номера хранятся как 2s-дополнение. Для простоты предположим, что это 1-байтовое целое число со знаком, то -101 будет храниться в

1 0000 0000 (256) 
- 0110 0101 (101) 
= 1001 1011 (155 if it were unsigned, -101 in signed) 

Когда бит сдвига отрицательное число, то правую панель с 1 с вместо 0 с (в противном случае вы» d теряют знаковый бит), поэтому результат:

1001 1011 
     >> 1 
= 1100 1101 

Это 205, если это целое число без знака. Затем 2s-дополнить его обратно, чтобы решить 256 - x = 205 =>x = 51

Ta-da? : D

+0

Это неполное. Вам нужно объяснить, что 'i' на самом деле является float, но операнды' >> 'преобразуются в 32-битные ints, а результат преобразуется обратно в float. – EML

+0

Я прочитал книгу и обновил вопрос, как вы думаете, мои объяснения верны? – Cheng

Смежные вопросы