Как мне преобразовать целое число в двоичное в JavaScript?

299

Я хотел бы видеть целые числа, положительные или отрицательные, в двоичном виде.

Скорее как этот вопрос , но для JavaScript.

barlop
источник
2
примеры a.toString (2), кажется, не работают для -1
barlop
1
Также возможно преобразовать двоичный код в десятичный: stackoverflow.com/questions/11103487/…
Андерсон Грин,
И когда я сказал «в двоичном формате», это может быть немного двусмысленным. Я имею в виду внутреннее представление строки битов, которое является дополнением 2s, поэтому положительные числа будут в базе 2 и с начальным 0, (и отрицательные числа не будут записываться с символом минус или с представлением величины знака, но как функция их положительного эквивалента)
Barlop

Ответы:

499
function dec2bin(dec){
    return (dec >>> 0).toString(2);
}

dec2bin(1);    // 1
dec2bin(-1);   // 11111111111111111111111111111111
dec2bin(256);  // 100000000
dec2bin(-256); // 11111111111111111111111100000000

Вы можете использовать Number.toString(2)функцию, но у нее есть некоторые проблемы при представлении отрицательных чисел. Например, (-1).toString(2)вывод есть "-1".

Чтобы решить эту проблему, вы можете использовать битовый оператор беззнакового сдвига вправо ( >>>), чтобы привести ваш номер к целому числу без знака.

Если вы запустите, (-1 >>> 0).toString(2)вы сдвинете свои биты числа 0 вправо, что само по себе не изменит число, но будет представлено как целое число без знака. Код выше выведет "11111111111111111111111111111111"правильно.

Этот вопрос имеет дальнейшее объяснение.

-3 >>> 0 (правый логический сдвиг) приводит его аргументы к целым числам без знака, поэтому вы получаете 32-битное представление дополнения до двух -3.

fernandosavio
источник
7
Вот объяснение
Фернандосавио
я давно пробовал javascript, но пробовал здесь w3schools.com/js/tryit.asp?filename=tryjs_output_alert с этим <script> window.alert ((- 3 >>> 0) .toString (2)); </ script> да, это сработало
barlop
1
toString (2) не работает, потому что вы получаете ввод из текста. Используйте это: function decToBase (dec, base) {return parseInt (dec) .toString (base); } alert (decToBase (dec, 2));
Волхв
Вы предполагаете, что ввод - это текст, но функция в ответе ожидает целое число ... Итак, если ввод - это текст, просто конвертируйте его в целое число, используйте поддельное смещение по битам, и все готово
fernandosavio
@ Магус, кто получает информацию из текста ?!
Бароп
207

Пытаться

num.toString(2);

2 является основанием и может быть любым основанием от 2 до 36

источник здесь

ОБНОВИТЬ:

Это будет работать только для положительных чисел, Javascript представляет отрицательные двоичные целые числа в двоичной записи. Я сделал эту маленькую функцию, которая должна была сделать свое дело, я не проверил это должным образом:

function dec2Bin(dec)
{
    if(dec >= 0) {
        return dec.toString(2);
    }
    else {
        /* Here you could represent the number in 2s compliment but this is not what 
           JS uses as its not sure how many bits are in your number range. There are 
           some suggestions /programming/10936600/javascript-decimal-to-binary-64-bit 
        */
        return (~dec).toString(2);
    }
}

Я получил некоторую помощь отсюда

Manatok
источник
не работает на -1. а = -1; document.write (Количество (a.toString (2))); отображает -1
barlop
Обновление по-прежнему не работает для отрицательных чисел ( -3возврат 1). Также я считаю, что dec > 0должно быть dec >= 0, которое должно по крайней мере исправить 0. Потому что dec2Bin(0)возвращается 10.
Адам Меррифилд
Оба случая в приведенных выше комментариях возвращают правильный результат в моей консоли chrome - var a = -1; a.toString (2); "-1" var a = -3; a.toString (2); "-11"
Anmol Saraf
@AnmolSaraf Я понимаю, что вы имеете в виду, и в то время как в разговорной речи люди говорят, что -5 в десятичной дроби, и ответ -5 Когда дело доходит до отрицательных чисел в двоичном, в некотором смысле, да, вы могли бы вставить знак минус, так что 5 это 101 и -5 - это -101, но поскольку компьютеры не хранят знаки минус, они просто представляют 1 и 0, поэтому, когда мы говорим отрицательные числа в двоичном виде, мы действительно имеем в виду помещение отрицательного числа (включая знак минус) в 1 и 0. Некоторые способы включают в себя 1-е дополнение, 2-е дополнение и «знак и величина». Таким образом, -101010101 или -0101010 - это не то, что люди подразумевают под отрицательным числом в двоичной системе.
Бароп
Эта ссылка может быть интересна для какого-то stackoverflow.com/questions/12337360/… во всяком случае, ваш ответ противоречит самому себе, вы пишете: «Javascript представляет отрицательные двоичные целые числа в двоичной записи». И ваш код говорит: «Здесь вы можете представить число в комплименте 2s, но это не то, что JS использует как [бессмысленная причина]». И вы также не даете никаких ссылок.
Barlop
53

Двоичный файл в «преобразовать в двоичный» может относиться к трем основным вещам. Позиционная система счисления, двоичное представление в памяти или 32-битные цепочки битов. (для 64-битных цепочек см. ответ Патрика Робертса )

1. Система счисления

(123456).toString(2)преобразует числа в основную 2-х позиционную систему счисления . В этой системе отрицательные числа пишутся со знаками минус, как в десятичной.

2. Внутреннее Представительство

Внутреннее представление чисел - 64-битная с плавающей запятой, и в этом ответе обсуждаются некоторые ограничения . Нет простого способа создать представление битовой строки в javascript или получить доступ к конкретным битам.

3. Маски и побитовые операторы

MDN имеет хороший обзор того, как работают побитовые операторы. Важно отметить:

Побитовые операторы обрабатывают свои операнды как последовательность из 32 битов (нули и единицы)

Перед применением операций 64-разрядные числа с плавающей запятой приводятся к 32-разрядным целым числам со знаком. После они обращены обратно.

Вот пример кода MDN для преобразования чисел в 32-битные строки.

function createBinaryString (nMask) {
  // nMask must be between -2147483648 and 2147483647
  for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
       nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
  return sMask;
}

createBinaryString(0) //-> "00000000000000000000000000000000"
createBinaryString(123) //-> "00000000000000000000000001111011"
createBinaryString(-1) //-> "11111111111111111111111111111111"
createBinaryString(-1123456) //-> "11111111111011101101101110000000"
createBinaryString(0x7fffffff) //-> "01111111111111111111111111111111"
AnnanFay
источник
В чем преимущество использования этой функции вместо простого Number (num) .toString (2)?
Волхв
5
@Magus Я думаю, что я адекватно объясняю различия между цифрами и двоичными строками. 32-битная двоичная строка всегда состоит из тридцати двух символов, состоящих из «1» и «0». toString возвращает фактическое число, представленное с использованием позиционных систем счисления с заданной базой. Это зависит от того, почему вы хотите строку, они имеют совершенно разные значения.
AnnanFay
извини, ты прав. Я прыгнул прямо к коду.
Волхв
1
Возникла проблема с ведущими нулями с использованием других опубликованных методов (в частности, с этим номером 536870912 удаляются два ведущих нуля), но это решение решило проблему правильно.
UberMouse
@UberMouse, да, у >>> есть ведущая проблема 0, я приму это.
Барлоп
43

Простой способ это просто ...

Number(42).toString(2);

// "101010"
рекламные объявления
источник
24
Я бы предпочел(42).toString(2)
Willem D'Haeseleer
33
Или еще короче42..toString(2)
капекс
9
Люди борются с этим. Ответ правильный, потому что он преобразует входные данные (42) в целое число, и эта строка необходима. Если вы получите свой «номер» из текстового ввода, toString (2) не будет работать.
Волхв
4
@ Kapep, чувак, это гений. Как вы узнали об этом?
Pacerier
2
@BatuG. Синтаксис для чисел позволяет опустить часть после десятичного разделителя. Вы можете написать 1.то же, что 1.0или просто 1(и аналогично вы можете опустить часть раньше и написать .5вместо 0.5). Таким образом, в примере первая точка - это десятичный разделитель, который является частью числа, а вторая точка - это оператор точки для вызова метода для этого числа. Вы должны использовать две точки (или заключить число в круглые скобки) и не можете просто написать, 42.toString(2)потому что анализатор видит точку как десятичный разделитель и выдает ошибку из-за пропущенного оператора точки.
Kapex
30

Этот ответ пытается адресовать входы с абсолютным значением в диапазоне 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


В JavaScript числа хранятся в 64-битном представлении с плавающей запятой , но побитовые операции приводят их к 32-битным целым числам в формате дополнения до двух , поэтому любой подход, использующий побитовые операции, ограничивает диапазон вывода до -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

Однако, если побитовые операции исключаются и 64-битное представление с плавающей запятой сохраняется с использованием только математических операций, мы можем надежно преобразовать любое безопасное целое число в 64-битную двоичную запись дополнения до двух, расширяя знак 53-бит twosComplement:

function toBinary (value) {
  if (!Number.isSafeInteger(value)) {
    throw new TypeError('value must be a safe integer');
  }

  const negative = value < 0;
  const twosComplement = negative ? Number.MAX_SAFE_INTEGER + value + 1 : value;
  const signExtend = negative ? '1' : '0';

  return twosComplement.toString(2).padStart(53, '0').padStart(64, signExtend);
}

function format (value) {
  console.log(value.toString().padStart(64));
  console.log(value.toString(2).padStart(64));
  console.log(toBinary(value));
}

format(8);
format(-8);
format(2**33-1);
format(-(2**33-1));
format(2**53-1);
format(-(2**53-1));
format(2**52);
format(-(2**52));
format(2**52+1);
format(-(2**52+1));
.as-console-wrapper{max-height:100%!important}

В старых браузерах существуют полифилы для следующих функций и значений:

В качестве дополнительного бонуса вы можете поддержать любое основание (2–36), если выполните преобразование дополнения до двух для отрицательных чисел в ⌈64 / log 2 (основание) ⌉, используя BigInt:

function toRadix (value, radix) {
  if (!Number.isSafeInteger(value)) {
    throw new TypeError('value must be a safe integer');
  }

  const digits = Math.ceil(64 / Math.log2(radix));
  const twosComplement = value < 0
    ? BigInt(radix) ** BigInt(digits) + BigInt(value)
    : value;

  return twosComplement.toString(radix).padStart(digits, '0');
}

console.log(toRadix(0xcba9876543210, 2));
console.log(toRadix(-0xcba9876543210, 2));
console.log(toRadix(0xcba9876543210, 16));
console.log(toRadix(-0xcba9876543210, 16));
console.log(toRadix(0x1032547698bac, 2));
console.log(toRadix(-0x1032547698bac, 2));
console.log(toRadix(0x1032547698bac, 16));
console.log(toRadix(-0x1032547698bac, 16));
.as-console-wrapper{max-height:100%!important}

Если вас интересует мой старый ответ, в котором ArrayBufferдля создания союза между a Float64Arrayи a использовался знак « Uint16Arrayпожалуйста», обратитесь к истории изменений этого ответа .

Патрик Робертс
источник
Спасибо, это хорошо, что это работает для 64-битной версии. Можете ли вы дать мне знать преимущества этого ответа перед ответом Аннана?
Барлоп
2
Намного больший диапазон? Он работает , -(2**53)-1чтобы 2**53-1вместо того , чтобы просто , -(2**31)чтобы 2**31-1как ответ Аннана.
Патрик Робертс
Да, это большое преимущество, я это понимаю, и это подойдет, хотя это немного больше кода, но что я имел в виду, мне любопытно, есть ли другие преимущества?
Барлоп
1
начиная с 2 ** 32 + 1, последний (самый правый) бит сбрасывается, когда он должен быть установлен.
Lovro
1
Работает, когда строка имеет вид: var exponent = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Lovro
15

Решение, которое я выбрал бы для 32-битного кода, - это конец этого ответа, код от developer.mozilla.org (MDN), но с некоторыми добавленными строками для A) форматирования и B) проверки того, что номер находится в диапазоне.

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

Фернандо упомянул простое решение, (x>>>0).toString(2);которое подходит для негативов, но имеет небольшую проблему, когда х положительно. Вывод начинается с 1, что для положительных чисел не является правильным дополнением 2s.

Любой, кто не понимает факт положительных чисел, начинающихся с 0 и отрицательных чисел с 1, в дополнении 2s, может проверить эту SO QnA на дополнении 2s. Что такое «дополнение 2»?

Решение может заключаться в добавлении 0 для положительных чисел, что я и сделал в более ранней редакции этого ответа. И иногда можно принять 33-битное число или убедиться, что конвертируемое число находится в пределах диапазона - (2 ^ 31) <= x <2 ^ 31-1. Таким образом, число всегда составляет 32 бита. Но вместо того, чтобы сделать это, вы можете пойти с этим решением на mozilla.org

Ответ и код Патрика длинный и, по-видимому, работает для 64-битной системы, но имел ошибку, которую нашел комментатор, и комментатор исправил ошибку Патрика, но у Патрика в коде есть какое-то «магическое число», о котором он не комментировал и имеет о котором забыли, и Патрик больше не полностью понимает свой собственный код / ​​почему он работает.

У Аннана была неправильная и неясная терминология, но он упомянул решение от developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators. Это работает для 32-разрядных чисел.

Код довольно компактный, функция из трех строк.

Но я добавил регулярное выражение для форматирования вывода в группы по 8 бит. Основано на том, как напечатать число с запятыми в качестве разделителей тысяч в JavaScript (я только что изменил его: сгруппировать его в 3 с справа налево и добавить запятые , сгруппировать в 8 с справа налево и добавить пробелы )

И хотя mozilla прокомментировала размер nMask (число вводимых) ... что он должен находиться в диапазоне, они не проверяли и не выдавали ошибку, когда число выходит за пределы диапазона, поэтому я добавил это.

Я не уверен, почему они назвали свой параметр 'nMask', но я оставлю это как есть.

Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

function createBinaryString(nMask) {
  // nMask must be between -2147483648 and 2147483647
  if (nMask > 2**31-1) 
     throw "number too large. number shouldn't be > 2**31-1"; //added
  if (nMask < -1*(2**31))
     throw "number too far negative, number shouldn't be < 2**31" //added
  for (var nFlag = 0, nShifted = nMask, sMask = ''; nFlag < 32;
       nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
  sMask=sMask.replace(/\B(?=(.{8})+(?!.))/g, " ") // added
  return sMask;
}


console.log(createBinaryString(-1))    // "11111111 11111111 11111111 11111111"
console.log(createBinaryString(1024))  // "00000000 00000000 00000100 00000000"
console.log(createBinaryString(-2))    // "11111111 11111111 11111111 11111110"
console.log(createBinaryString(-1024)) // "11111111 11111111 11111100 00000000"

barlop
источник
8

Вы можете написать свою собственную функцию, которая возвращает массив битов. Пример как преобразовать число в биты

Делитель | Дивидендная | бит / остаточный

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 | ~

Пример вышеприведенной строки: 2 * 4 = 8, а остаток равен 1, поэтому 9 = 1 0 0 1

function numToBit(num){
    var number = num
    var result = []
    while(number >= 1 ){
        result.unshift(Math.floor(number%2))
        number = number/2
    }
    return result
}

Читайте остатки снизу вверх. Цифра 1 посередине вверх.

supritshah1289
источник
1
Кстати, почему ты Math.floor(number%2)вместо number = Math.floor(number/2)?
Pacerier
1
Причина в том, что число% 2 не равно числу / 2. Мы заинтересованы в том, чтобы остаток не был частным.
supritshah1289
0

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

  • Не использует сдвиг битов или принуждение к дополнению до двух.
  • Вы выбираете количество получаемых битов (оно проверяет действительные значения '8', '16', '32', но я полагаю, вы можете изменить это)
  • Вы выбираете, следует ли рассматривать его как целое число со знаком или без знака.
  • Он проверит наличие проблем с диапазоном, учитывая комбинацию со знаком / без знака и количеством битов, хотя вы захотите улучшить обработку ошибок.
  • Он также имеет «обратную» версию функции, которая преобразует биты обратно в int. Вам это понадобится, так как, вероятно, больше ничего не будет интерпретировать этот вывод: D

function intToBitString(input, size, unsigned) {
	if ([8, 16, 32].indexOf(size) == -1) {
		throw "invalid params";
	}
	var min = unsigned ? 0 : - (2 ** size / 2);
        var limit = unsigned ? 2 ** size : 2 ** size / 2;
	if (!Number.isInteger(input) || input < min || input >= limit) {
		throw "out of range or not an int";
	}
	if (!unsigned) {
		input += limit;
	}
	var binary = input.toString(2).replace(/^-/, '');
	return binary.padStart(size, '0');
}

function bitStringToInt(input, size, unsigned) {
	if ([8, 16, 32].indexOf(size) == -1) {
		throw "invalid params";
	}
	input = parseInt(input, 2);
	if (!unsigned) {
		input -= 2 ** size / 2;
	}
	return input;
}


// EXAMPLES

var res;
console.log("(uint8)10");
res = intToBitString(10, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(uint8)127");
res = intToBitString(127, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(int8)127");
res = intToBitString(127, 8, false);
console.log("intToBitString(res, 8, false)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, false));
console.log("---");

console.log("(int8)-128");
res = intToBitString(-128, 8, false);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");

console.log("(uint16)5000");
res = intToBitString(5000, 16, true);
console.log("intToBitString(res, 16, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 16, true));
console.log("---");

console.log("(uint32)5000");
res = intToBitString(5000, 32, true);
console.log("intToBitString(res, 32, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 32, true));
console.log("---");

braks
источник
-1

Еще одна альтернатива

const decToBin = dec => {
  let bin = '';
  let f = false;

  while (!f) {
    bin = bin + (dec % 2);    
    dec = Math.trunc(dec / 2);  

    if (dec === 0 ) f = true;
  }

  return bin.split("").reverse().join("");
}

console.log(decToBin(0));
console.log(decToBin(1));
console.log(decToBin(2));
console.log(decToBin(3));
console.log(decToBin(4));
console.log(decToBin(5));
console.log(decToBin(6));
Иван Проскуряков
источник
Пожалуйста, ознакомьтесь с ответом Винсента и комментарием к нему, это будет относиться и к вашей публикации
barlop
Это то, что было опубликовано в комментарии к его ответу, без разногласий и с некоторым согласием других: «Это может быть полезно для изучения информатики, чтобы увидеть, как сделать это вручную, чтобы научить себя, но это не то, что я Прошу! Если вы собираетесь заново изобрести колесо, делая это вручную таким образом, то это должно быть, по крайней мере, с преимуществом увеличения эффективности или некоторого преимущества, такого как увеличение размера значений, с которыми оно может справиться. Я не вижу любая дискуссия с твоей стороны о том, что там есть такое преимущество "
Бароп
Кроме того, ваше решение полностью терпит неудачу, оно заставляет положительные числа начинаться с 1 и полностью терпит неудачу для отрицательных чисел, а мой вопрос упоминается как положительный или отрицательный
barlop
Таким образом, ваш «ответ» неверен на многих уровнях. И вы должны всегда просматривать другие ответы, прежде чем отправлять ответ
barlop
-2

Это мой код:

var x = prompt("enter number", "7");
var i = 0;
var binaryvar = " ";

function add(n) {
    if (n == 0) {
        binaryvar = "0" + binaryvar; 
    }
    else {
        binaryvar = "1" + binaryvar;
    }
}

function binary() {
    while (i < 1) {
        if (x == 1) {
            add(1);
            document.write(binaryvar);
            break;
        }
        else {
            if (x % 2 == 0) {
                x = x / 2;
                add(0);
            }
            else {
                x = (x - 1) / 2;
                add(1);
            }
        }
    }
}

binary();
Винсент Уильям Родригес
источник
3
Это может быть полезно для изучения информатики, чтобы увидеть, как сделать это вручную, чтобы научить себя, но это не то, что я спрашиваю! Если вы собираетесь заново изобрести колесо, выполнив это вручную, то это должно быть, по крайней мере, с преимуществом увеличения эффективности или некоторого преимущества, такого как увеличение размера значений, с которыми оно может справиться. Я не вижу никакой дискуссии о том, что вы заявляете о таком преимуществе.
Бароп
-3

Это решение. Это довольно просто на самом деле

function binaries(num1){ 
        var str = num1.toString(2)
        return(console.log('The binary form of ' + num1 + ' is: ' + str))
     }
     binaries(3

)

        /*
         According to MDN, Number.prototype.toString() overrides 
         Object.prototype.toString() with the useful distinction that you can 
         pass in a single integer argument. This argument is an optional radix, 
         numbers 2 to 36 allowed.So in the example above, we’re passing in 2 to 
         get a string representation of the binary for the base 10 number 100, 
         i.e. 1100100.
        */
Брайан
источник
1
Это решение уже предлагалось много раз, и, как прокомментировал OP уже 30 марта 12 в 9:01, не работает для отрицательных чисел.
Адриан W
@AdrianW Я предлагаю понизить это. Я заметил, что у вас нет. Что вам нужно, чтобы понизить ответ?
Barlop