Почему JavaScript побитовый ИЛИ ведет себя странно?
В JavaScript это выглядит так:
(4294958077 | 0) == -9219
Почему это не 4294958077?
Это говорит о том, что происходит какое-то переполнение (хотя, насколько я понимаю, диапазон типа номера JavaScript равен +/- 9007199254740992, так что это странно само по себе.)
Даже если это было переполнение, конечно
(4294958077 | 0) == 4294958077
следует оценивать как истинное - но это не так.
Помогите, пожалуйста
3 ответа
Это не имеет ничего общего с типом с плавающей запятой или переполнением. Он возвращает -9219, потому что стандарт предписывает его, так как все двоичные побитовые операции должны выполняться с использованием 32-разрядных целых чисел со знаком (ECMA-262 §11.10).
Производство A: A @ B, где @ - один из побитовых операторов в приведенных выше производствах, оценивается следующим образом:
- Пусть lref будет результатом оценки A.
- Пусть lval будет GetValue (lref).
- Пусть rref будет результатом оценки B.
- Пусть rval будет GetValue (rref).
- Пусть lnum будет ToInt32 (lval).
- Пусть rnum будет ToInt32 (rval).
- Вернуть результат применения побитового оператора @ к lnum и rnum. Результатом является 32-разрядное целое число со знаком.
4294958077, преобразованное в 32-разрядное целое число со знаком (с использованием алгоритма в ECMA-262 §9.5), равно -9219, а 0 по-прежнему равно 0, поэтому поразрядное или возвращает -9219.
Все числа в Javascript являются 64-битными числами с плавающей точкой. Побитовые операции над числами с плавающей запятой являются крайним случаем, поэтому внутренне эти числа с плавающей запятой временно преобразуются в 32-битное целое число, затем выполняется побитовая операция - отсюда ваше переполнение.
Побитовые числа JavaScript хранятся в виде 64-разрядных чисел со знаком, т. Е. У вас есть только 32-разрядные числа, которые вы можете использовать для целого числа, которое вы превысили, поэтому это становится странным, если преобразовать его в целое число как можно лучше, а затем выполнить операцию.
Здесь больше информации (особенно раздел "за пределами 32-битной версии"), но нет реального решения, поэтому, к сожалению, вам придется обойти его.