Почему JavaScript побитовый ИЛИ ведет себя странно?

В JavaScript это выглядит так:

(4294958077 | 0) == -9219

Почему это не 4294958077?

Это говорит о том, что происходит какое-то переполнение (хотя, насколько я понимаю, диапазон типа номера JavaScript равен +/- 9007199254740992, так что это странно само по себе.)

Даже если это было переполнение, конечно

(4294958077 | 0) == 4294958077

следует оценивать как истинное - но это не так.

Помогите, пожалуйста

3 ответа

Решение

Это не имеет ничего общего с типом с плавающей запятой или переполнением. Он возвращает -9219, потому что стандарт предписывает его, так как все двоичные побитовые операции должны выполняться с использованием 32-разрядных целых чисел со знаком (ECMA-262 §11.10).

Производство A: A @ B, где @ - один из побитовых операторов в приведенных выше производствах, оценивается следующим образом:

  1. Пусть lref будет результатом оценки A.
  2. Пусть lval будет GetValue (lref).
  3. Пусть rref будет результатом оценки B.
  4. Пусть rval будет GetValue (rref).
  5. Пусть lnum будет ToInt32 (lval).
  6. Пусть rnum будет ToInt32 (rval).
  7. Вернуть результат применения побитового оператора @ к lnum и rnum. Результатом является 32-разрядное целое число со знаком.

4294958077, преобразованное в 32-разрядное целое число со знаком (с использованием алгоритма в ECMA-262 §9.5), равно -9219, а 0 по-прежнему равно 0, поэтому поразрядное или возвращает -9219.

Все числа в Javascript являются 64-битными числами с плавающей точкой. Побитовые операции над числами с плавающей запятой являются крайним случаем, поэтому внутренне эти числа с плавающей запятой временно преобразуются в 32-битное целое число, затем выполняется побитовая операция - отсюда ваше переполнение.

Побитовые числа JavaScript хранятся в виде 64-разрядных чисел со знаком, т. Е. У вас есть только 32-разрядные числа, которые вы можете использовать для целого числа, которое вы превысили, поэтому это становится странным, если преобразовать его в целое число как можно лучше, а затем выполнить операцию.

Здесь больше информации (особенно раздел "за пределами 32-битной версии"), но нет реального решения, поэтому, к сожалению, вам придется обойти его.

Другие вопросы по тегам