Отрицательные числа для двоичной строки в 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
Короткий ответ:
-
Функция toString()
принимает десятичное число, преобразует его в двоичный и добавляет знак "-".
-
Сдвиг вправо с нулевым заполнением преобразует его операнды в 32-разрядные целые числа со знаком в формате двух дополнений.
Более подробный ответ:
Вопрос 1:
//If you try
(-3).toString(2); //show "-11"
Это в функции .toString()
. Когда вы выводите число через .toString()
:
Синтаксис
numObj.toString([Radix])
Если numObj отрицательный, знак сохраняется. Это имеет место, даже если основание равно 2; возвращаемая строка является положительным двоичным представлением numObj, которому предшествует знак -, а не дополнение двух к numObj.
Он принимает десятичное число, преобразует его в двоичный файл и добавляет знак "-".
- База 10 "3", преобразованная в базу 2, это "11"
- Добавить знак дает нам "-11"
Вопрос 2:
// but if you fake a bit shift operation it works as expected
(-3 >>> 0).toString(2); // print "11111111111111111111111111111101"
Сдвиг вправо с нулевым заполнением преобразует его операнды в 32-разрядные целые числа со знаком. Результатом этой операции всегда является 32-разрядное целое число без знака.
Операнды всех побитовых операторов преобразуются в 32-разрядные целые числа со знаком в формате двух дополнений.
Ответ 2
-3 → > 0 (правый логический сдвиг) приводит в порядок свои аргументы к целым без знака, поэтому вы получаете 32-битное представление двух дополнений -3.
http://en.wikipedia.org/wiki/Two%27s_complement
http://en.wikipedia.org/wiki/Logical_shift
Ответ 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:
- Если m меньше нуля, вернуть конкатенацию String строки "-" и ToString (−m).
Это правило не отличается для случая, когда основание передается в качестве аргумента, как можно заключить из раздела 20.1.3.6:
- Вернуть строковое представление этого значения Number, используя radix, указанный в radixNumber. [...] алгоритм должен быть обобщением того, что указано в 7.1.12.1.
Как только это понято, удивительно, что он не делает то же самое с -3 >>> 0
.
Но это поведение на самом деле не имеет ничего общего с .toString(2)
, так как значение уже другое перед вызовом:
console.log (-3 >>> 0); // 4294967293