Подтвердить что ты не робот

Побитовые операции с 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 */
4b9b3361

Ответ 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 заботится об этой проблеме, предлагая два оператора смены битов, >> и >>>. Вы хотите, чтобы >>> выполнял сдвиг без сдвига знака.