Отрицательные числа для двоичной строки в JavaScript

Кто-нибудь знает, почему функция javascript Number.toString неверно отображает отрицательные числа?

//If you try
(-3).toString(2); //shows "-11"
// but if you fake a bit shift operation it works as expected
(-3 >>> 0).toString(2); // print "11111111111111111111111111111101"

Мне действительно интересно, почему это не работает должным образом или по какой причине он работает именно так? Я искал его, но не нашел ничего, что помогло.

Ответ 1

Короткий ответ:

  1. Функция toString() принимает десятичное число, преобразует его в двоичный и добавляет знак "-".

  2. Сдвиг вправо с нулевым заполнением преобразует его операнды в 32-разрядные целые числа со знаком в формате двух дополнений.

Более подробный ответ:

Вопрос 1:

//If you try
(-3).toString(2); //show "-11"

Это в функции .toString(). Когда вы выводите число через .toString():

Синтаксис

numObj.toString([Radix])

Если numObj отрицательный, знак сохраняется. Это имеет место, даже если основание равно 2; возвращаемая строка является положительным двоичным представлением numObj, которому предшествует знак -, а не дополнение двух к numObj.

Он принимает десятичное число, преобразует его в двоичный файл и добавляет знак "-".

  1. База 10 "3", преобразованная в базу 2, это "11"
  2. Добавить знак дает нам "-11"

Вопрос 2:

// but if you fake a bit shift operation it works as expected
        (-3 >>> 0).toString(2); // print "11111111111111111111111111111101"

Сдвиг вправо с нулевым заполнением преобразует его операнды в 32-разрядные целые числа со знаком. Результатом этой операции всегда является 32-разрядное целое число без знака.

Операнды всех побитовых операторов преобразуются в 32-разрядные целые числа со знаком в формате двух дополнений.

Ответ 3

var binary = (-3 >>> 0).toString(2); // coerced to uint32

console.log(binary);

console.log(parseInt(binary, 2) >> 0); // to int32

on jsfiddle

вывод

11111111111111111111111111111101
-3 

Ответ 4

.toString() предназначен для возврата знака числа в строковом представлении. См. EcmaScript 2015, раздел 7.1.12.1:

  1. Если m меньше нуля, вернуть конкатенацию String строки "-" и ToString (−m).

Это правило не отличается для случая, когда основание передается в качестве аргумента, как можно заключить из раздела 20.1.3.6:

  1. Вернуть строковое представление этого значения Number, используя radix, указанный в radixNumber. [...] алгоритм должен быть обобщением того, что указано в 7.1.12.1.

Как только это понято, удивительно, что он не делает то же самое с -3 >>> 0.

Но это поведение на самом деле не имеет ничего общего с .toString(2), так как значение уже другое перед вызовом:

console.log (-3 >>> 0); // 4294967293