Почему побитовый сдвиг с 0 в JavaScript дает странные результаты в некоторых случаях


Просто поиграл с необычными побитовыми операциями в JavaScript, и в некоторых случаях я получил странные результаты:

обычные случаи

1 << 0            // returns 1, makes sense
100 << 0          // returns 100, makes sense
100 >> 0          // returns 100, definitely makes sense

но эти, при сдвиге на 0 бит, все дают ноль

9E99 << 0         // returns 0 ..... Why all bits are cleared?
9E99 >> 0         // returns 0 also  ..... All bits cleared?
Infinity >> 0     // returns 0
Infinity << 0     // returns 0
-Infinity << 0    // returns 0 .... Can't explain why
-0 << 0           // also yields 0 not -0 itself
-0 >> 0           // also resolved to 0

что если бесконечность и побитовое смещение

1 << Infinity     // returns 1  .. no changes
1024 << Infinity  // returns 1024 .. no changes
1024 >> Infinity  // returns 1024 .. no changes either
Infinity >> Infinity      // 0
Infinity << Infinity      // 0
Эти случаи выше не имеют для меня особого смысла. при сдвиге целого числа на ноль бит значение не изменяется . но когда вы сдвигаете Infinity на 0 бит, он фактически возвращает Вас 0. Почему?

Я думал, что сдвиг любого числового значения на 0 бит не должен изменить его значение, не так ли?

Далее, при сдвиге небольшого целого значения на бесконечность бит, значение не изменяется вообще. Но когда вы сдвигаете бесконечность на любые значения,она заменяется на 0.

Мне действительно интересно, почему происходят эти явления? Существуют ли какие-либо спецификации или теории, объясняющие эти странные формы поведения?
3 4

3 ответа:

Из MDN:

Операнды всех побитовых операторов преобразуются в 32-разрядные целые числа со знаком в формате дополнения two.

Все числа в JavaScript являютсяIEEE754 числами с плавающей запятой двойной точности . Они преобразуются в 32-битные целые числа перед применением побитовых операторов.

Точнее, этот процесс описан в ToInt32 в спецификации :

Введите описание изображения здесь

Как вы видите, трансформация Бесконечности и -0 точно описаны.

Это двоичное усечение, которое также объясняет, почему 9E99 изменяется на 0: это наиболее очевидно, если вы посмотрите на 32 бита справа от (9E99).toString(2) (вставьте его в консоль, они все 0).

Битовые сдвиги и логические операции в JavaScript оцениваются как 32-битные целые числа. Наличие оператора

Это работает в обоих направлениях: inf

Это соответствует ECMA-262.

В основном, JS компилятор преобразует аргументы с плавающей запятой в 32-битное целое число, используя алгоритм, описанный в п. 9.5 ECMA-262. В большинстве случаев, о которых вы упомянули, результат преобразования равен 0.