Побитовые операции с 32-битными беззнаковыми ints?
JavaScript преобразует операнды в 32-разрядные подписанные int перед выполнением побитовых операций. Он также выполняет операцию с 32-битными подписанными int, что означает, что результатом является 32-разрядный подписанный int.
Поскольку я хотел бы выполнять побитовые операции с 32-битными беззнаковыми ints, мне интересно, есть ли способ использовать искаженный JavaScript результат, чтобы узнать предполагаемый результат.
Чтобы продемонстрировать мою идею, например, в C, которая является ссылкой на то, что я хотел бы,
unsigned int a = 3774191835u;
unsigned int b = a >> 2;
/* b == 943547958 */
В JavaScript,
var a = 3774191835;
var b = a >> 2;
/* b == -130193866 */
Попробуйте это с другой операцией. В C,
unsigned int a = 1986735448u;
unsigned int b = a << 1;
/* b == 3973470896 */
В JavaScript,
var a = 1986735448;
var b = a << 1;
/* b == -321496400 */
Теперь, когда JavaScript оценил мою поразрядную операцию с операндом как подписанный int, мы, конечно же, получим другой результат для того, что мы будем делать в C, где мы можем корректно выполнять побитовые операции с неподписанными ints.
Я знаю, что это возможно, но я не уверен в том, что могу, по существу, превратить результат JavaScript в предполагаемый результат.
Zero-fill right сдвигает результат на нулевые работы только для второго случая, но не для первого.
var a = 3774191835;
var b = (a >> 2) >>> 0;
/* b == 4164773430 */
var a = 1986735448;
var b = (a << 1) >>> 0;
/* b == 3973470896 */
Ответы
Ответ 1
Вам нужно только следовать этим правилам:
- всегда заканчивать бит мудрым ops с
>>> 0
, поэтому результат интерпретируется как unsigned.
- не используйте
>>
. Если самый левый бит равен 1, он попытается выставить знак и, таким образом, ввести 1
влево. Всегда используйте >>>
.
Примеры:
C: (3774191835 >> 2) | 2147483648
js: (3774191835 >>> 2 | 2147483648) >>> 0
C: 1986735448 << 1
js: (1986735448 << 1) >>> 0
C: 3774191835 & 4294967295
js: (3774191835 & 4294967295) >>> 0
Только если последний op равен >>>
, >>> 0
не требуется.
Ответ 2
Это уродливо, но:
var a = 1986735448;
var b = (a << 1) >>> 0;
/* b = 3973470896 */
Ответ 3
JavaScript заботится об этой проблеме, предлагая два оператора смены битов, >>
и >>>
. Вы хотите, чтобы >>>
выполнял сдвиг без сдвига знака.