Преобразование числа дополнения до двух в его двоичное представление - PullRequest
1 голос
/ 15 октября 2019

Я выполняю побитовые операции, результат которых, очевидно, сохраняется как число с дополнением до двух. При наведении курсора на переменную, в которой она хранится, я вижу - num = -2086528968.

Двоичный файл этого числа, который мне нужен, - (10000011101000100001100000111000).

Но когда я говорю num.toString(2), я получаю совершенно другое двоичное представление, двоичное необработанное число вместо 2s comp (-1111100010111011110011111001000).

Как получить первоеверёвка?

Ссылка на конвертер: rapidtables.com/convert/number/decimal-to-binary.html Введите этот номер: -2086528968

Ответы [ 2 ]

3 голосов
/ 15 октября 2019

Ниже приведен результат:

var number = -2086528968;
    
    var bin = (number >>> 0).toString(2)
    //10000011101000100001100000111000
    console.log(bin)
2 голосов
/ 15 октября 2019

Педро уже ответил на это, но так как это хак и не совсем интуитивно, я объясню это.

Я выполняю побитовые операции, результат которых, очевидно, сохраняется как двадополнить номер. При наведении курсора на переменную, хранящуюся в ней, я вижу num = -2086528968

Нет, результатом большинства битовых операций является 32-битное знаковое целое число. Это означает, что бит 0x80000000 интерпретируется как знак, за которым следует 31 бит значения.

Странная битовая последовательность из-за того, как JS строковое выравнивает значение, что-то вроде sign + Math.abs(value).toString(base);

Как с этим бороться? Нам нужно указать JS не интерпретировать этот бит как знак, а как часть значения. Но как?

Простым для понимания решением было бы добавить 0x100000000 к отрицательным числам и, следовательно, получить их положительные двойники.

function print(value) {
  if (value < 0) {
    value += 0x100000000;
  }
  console.log(value.toString(2).padStart(32, 0));
}

print(-2086528968);

Другим способом было бы преобразование нижнего и верхнего битов отдельно

function print(value) {
  var signBit = value < 0 ? "1" : "0";
  var valueBits = (value & 0x7FFFFFFF).toString(2);

  console.log(signBit + valueBits.padStart(31, 0));
}

print(-2086528968);


//or lower and upper half of the bits:
function print2(value) {
  var upperHalf = (value >> 16 & 0xFFFF).toString(2);
  var lowerHalf = (value & 0xFFFF).toString(2);
  console.log(upperHalf.padStart(16, 0) + lowerHalf.padStart(16, 0));
}

print2(-2086528968);

Другой способ связан с «взломом», который использует Педро. Вы помните, как я сказал, что большинство битовых операций возвращают int32? Есть одна операция, которая на самом деле возвращает беззнаковое (32-битное) интергер, так называемое смещение вправо с нулевым заполнением .

Итак number >>> 0 не изменяет биты числа, но первый бит больше не интерпретируется как знак.

function uint32(value){
  return value>>>0;
}

function print(value){
  console.log(uint32(value).toString(2).padStart(32, 0));
}

print(-2086528968);

Буду ли я запускать этот код переключения только тогда, когда число отрицательное или всегда?

Вообще говоря, вреда нетпри выполнении nr >>> 0 над положительными целыми числами, но будьте осторожны, чтобы не переусердствовать.

Технически JS поддерживает только числа, которые являются double значениями (64bit floating point значениями) . Внутренне двигатели также используют значения int32;где возможно. Но нет uint32 значений. Поэтому, когда вы конвертируете ваш отрицательный int32 в uint32, движок преобразует его в double. И если вы выполняете еще одну битовую операцию, первое, что она делает, - конвертирует ее обратно.

Так что это нормально делать, например, когда вам нужно фактическое значение uint32, например, напечатать биты здесь, ноВы должны избегать этого преобразования между операциями. Как "просто чтобы исправить это".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...