JavaScript указывает, что побитовые операции над целыми числами выполняются так, как если бы они хранились в двоичной записи .К счастью, в настоящее время большинство компьютерного оборудования использует эту нотацию изначально.
Для краткости я собираюсь показать следующие числа в виде 8-битного двоичного кода.Они на самом деле 32-битные в JavaScript, но для чисел в исходном вопросе это не меняет результат.Это, однако, позволяет нам отбросить много начальных битов.
console.log(-25 & -3); //outputs -27. How?
Если мы запишем целые числа в двоичном виде, мы получим (11100111 и 11111101) соответственно.И все вместе, и вы получите 11100101, что равно -27.
В ваших последующих примерах вы, кажется, используете операторы NOT (~) и отрицание (-) взаимозаменяемо.Вы не можете сделать это в дополнении к двум: ~ и - не одно и то же .~ 25 - это 11100110, то есть -26, а не -25.Точно так же, ~ 3 - это 11111100, то есть -4, а не -3.
Но когда мы сложим их вместе, мы сможем обработать приведенные вами примеры.
console.log(~25 & ~3); //outputs-28. How?
11100110 & 11111100= 11100100, что составляет -28 (а не 28, как вы написали)
console.log(25 & ~3);//outputs-24. How?
00011001 & 11111100 = 00011000, что составляет 24
console.log(~25 & 3);//outputs-2. How?
11100110 & 00000011 = 00000001, что2
console.log(~25 & -3);//outputs--28. How?
11100110 & 11111101 = 11100100, что составляет -28
console.log(-25 & ~3);//outputs--28. How?
11100111 & 11111100 = 11100100, что составляет -28
Реальный ключ к пониманиюэто то, что вы действительно не используете побитовые операции над целыми числами.Вы используете их на пакетах с битами определенного размера, и эти пакеты с битами удобно представить в виде целых чисел .Это ключ к пониманию того, что здесь происходит, потому что вы наткнулись на случай, когда разница имеет значение.
В компьютерной науке существуют особые обстоятельства, когда вы можете манипулировать мешками с битами таким образом, по совпадению , дать те же результаты, как если бы вы делали определенные математические операции над числами.Но это работает только в определенных обстоятельствах, и они требуют, чтобы вы предположили определенные вещи относительно чисел, с которыми вы работаете, и если ваши цифры не не соответствуют этим предположениям, все сломается.
Это одна из причин, по которой Дональд Кнут сказал, что «преждевременная оптимизация - корень всего зла».Если вы хотите использовать побитовые операции вместо действительной целочисленной математики, вы должны быть абсолютно уверены, что ваши входные данные действительно будут соответствовать предположениям, необходимым для работы этого трюка.В противном случае результаты начнут выглядеть странно, когда вы начнете использовать входные данные вне этих предположений.