Como converter um número inteiro em binário em JavaScript?

299

Eu gostaria de ver números inteiros, positivos ou negativos, em binário.

Um pouco como esta pergunta , mas para JavaScript.

barlop
fonte
2
o a.toString (2) exemplos não parecem trabalho para -1
barlop
1
Também é possível converter de binário para decimal: stackoverflow.com/questions/11103487/…
Anderson Green
E quando eu disse "em binário", isso pode ser um pouco ambíguo. Quero dizer, a representação interna da sequência de bits, que é o complemento 2s, portanto os números positivos estariam na base 2 e com um 0 inicial (e os números negativos não seriam escritos com um símbolo de menos ou com uma representação de magnitude de sinal, mas como um função de sua eqivalent positivo)
barlop

Respostas:

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

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

Você pode usar a Number.toString(2)função, mas há alguns problemas ao representar números negativos. Por exemplo, a (-1).toString(2)saída é "-1".

Para corrigir esse problema, você pode usar o operador bit a bit de deslocamento à direita não assinado ( >>>) para coagir seu número a um número inteiro não assinado.

Se você executar, (-1 >>> 0).toString(2)você deslocará seu número 0 bits para a direita, o que não altera o número em si, mas será representado como um número inteiro não assinado. O código acima será exibido "11111111111111111111111111111111"corretamente.

Esta pergunta tem mais explicações.

-3 >>> 0 (deslocamento lógico direito) força seus argumentos a números inteiros não assinados, e é por isso que você obtém a representação complementar de -3 de dois bits de 32 bits.

fernandosavio
fonte
7
Aqui está a explicação
fernandosavio
já faz um tempo desde que tentei o javascript, mas tentei aqui w3schools.com/js/tryit.asp?filename=tryjs_output_alert com este <script> window.alert ((- 3 >>> 0) .toString (2)); </ script> sim funcionou
barlop
1
toString (2) não funciona porque você está recebendo a entrada de texto. Use isto: function decToBase (dec, base) {return parseInt (dec) .toString (base); } alerta (decToBase (dec, 2));
Magus
Você está assumindo que a entrada é texto, mas a função na resposta esperam um inteiro ... Então, se a entrada é um texto apenas convertê-lo para inteiro, utilize o bitshift falso e está feito
fernandosavio
@ Magus quem está recebendo a entrada do texto ?!
#
207

Experimentar

num.toString(2);

O 2 é a raiz e pode ser qualquer base entre 2 e 36

fonte aqui

ATUALIZAR:

Isso funcionará apenas para números positivos. Javascript representa números inteiros binários negativos na notação complemento de dois. Eu criei essa pequena função que deve funcionar, não a testei corretamente:

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);
    }
}

Eu tive alguma ajuda daqui

Manatok
fonte
não funciona para -1. a = -1; document.write (Number (a.toString (2))); exibe -1
barlop
A atualização ainda não parece funcionar para números negativos ( -3retornos 1). Também acredito que dec > 0deveria ser dec >= 0, que deveria pelo menos consertar 0. Porque dec2Bin(0)retorna 10.
Adam Merrifield
Ambos os casos nos comentários acima retornam o resultado correto no meu console chrome - var a = -1; a.toString (2); "-1" var a = -3; a.toString (2); "-11"
Anmol Saraf
@AnmolSaraf Entendo o que você quer dizer, e embora coloquialmente quando as pessoas dizem o que é -5 em decimal, e a resposta é -5 101 e -5 é -101, mas como os computadores não armazenam sinais de menos, eles apenas representam 1s e 0s; portanto, quando dizemos números negativos em binário, queremos dizer colocar o número negativo (sinal de menos incluído) em 1s e 0s. Algumas maneiras incluem complemento 1s, complemento 2s e 'sinal e magnitude'. Portanto, -101010101 ou -0101010 não é o que as pessoas querem dizer com número negativo em binário.
barlop
Este link pode ser interessante para alguns stackoverflow.com/questions/12337360/… de qualquer maneira, sua resposta se contradiz, você escreve "Javascript representa números inteiros binários negativos na notação de complemento de dois". E seu código diz "Aqui você pode representar o número no complemento 2s, mas não é isso que JS usa como [razão sem sentido]". E você também não fornece referência.
barlop
53

O binário em 'converter em binário' pode se referir a três coisas principais. O sistema numérico posicional, a representação binária na memória ou as cadeias de bits de 32 bits. (para bits de 64 bits, veja a resposta de Patrick Roberts )

1. Sistema Numérico

(123456).toString(2)irá converter números para o sistema numérico posicional de base 2 . Neste sistema, os números negativos são escritos com sinais de menos, como em decimal.

2. Representação Interna

A representação interna dos números é ponto flutuante de 64 bits e algumas limitações são discutidas nesta resposta . Não existe uma maneira fácil de criar uma representação disso em javascript nem acessar bits específicos.

3. Máscaras e operadores bit a bit

O MDN tem uma boa visão geral de como os operadores bit a bit funcionam. Importante:

Operadores bit a bit tratam seus operandos como uma sequência de 32 bits (zeros e uns)

Antes da aplicação das operações, os números de pontos flutuantes de 64 bits são convertidos em números inteiros assinados de 32 bits. Depois que eles são convertidos de volta.

Aqui está o código de exemplo MDN para converter números em cadeias de 32 bits.

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
fonte
Qual é a vantagem de usar essa função em vez de usar um simples Number (num) .toString (2)?
Magus
5
@ Magus Acho que explico adequadamente as diferenças entre numerais e seqüências de caracteres binárias. Uma cadeia binária de 32 bits tem sempre trinta e dois caracteres, compostos por "1" se "0" s. toString retorna um número real representado usando os sistemas de números posicionais com a base especificada. Depende do motivo pelo qual você deseja a string, eles têm significados muito diferentes.
AnnanFay
desculpe, você está certo. Eu pulei direto para o código.
Magus
1
Ocorreu um problema com os 0s iniciais usando os outros métodos publicados (especificamente neste número 536870912, os dois zeros iniciais foram removidos), mas esta solução o tratou corretamente.
UberMouse 5/08/15
@UberMouse sim, o >>> tem o principal problema dos 0s, eu aceito esse.
Barlop
43

Uma maneira simples é apenas ...

Number(42).toString(2);

// "101010"
anúncios
fonte
24
Eu prefiro #(42).toString(2)
Willem D'Haeseleer 15/04
33
Ou ainda menor42..toString(2)
kapex:
9
As pessoas estão lutando com isso. A resposta está correta porque lança a entrada (42) em um número inteiro e essa linha é necessária. Se você obtiver seu 'número' de uma entrada de texto, o toString (2) não funcionará.
Magus
4
@ Kapep, Cara, isso é genial. Como você soube disso?
Pacerier
2
@BatuG. A sintaxe dos números permite omitir a parte após o separador decimal. Você pode escrever o 1.que é igual 1.0ou apenas 1(e da mesma forma também pode omitir a parte anterior e escrever em .5vez de 0.5). Portanto, no exemplo, o primeiro ponto é o separador decimal que faz parte do número e o segundo ponto é o operador de ponto para chamar o método nesse número. Você precisa usar dois pontos (ou colocar o número entre parênteses) e não pode escrever apenas 42.toString(2)porque o analisador vê o ponto como separador decimal e gera um erro devido a um operador de ponto ausente.
Kapex
30

Esta resposta tenta endereçar entradas com um valor absoluto no intervalo de 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


No JavaScript, os números são armazenados na representação de ponto flutuante de 64 bits , mas as operações bit a bit os coagem para números inteiros de 32 bits no formato de complemento de dois , portanto, qualquer abordagem que use operações bit a bit restringe o intervalo de saída a -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

No entanto, se as operações bit a bit forem evitadas e a representação de ponto flutuante de 64 bits for preservada usando apenas operações matemáticas, podemos converter com segurança qualquer número inteiro seguro na notação binária complementar de dois bits de 64 bits, estendendo o sinal de 53 bits 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}

Para navegadores mais antigos, existem polyfills para as seguintes funções e valores:

Como um bônus adicional, você pode suportar qualquer raiz (2–36) se realizar a conversão do complemento de dois para números negativos em dígitos ⌈64 / log 2 (raiz) by usando 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}

Se você estiver interessado na minha resposta antiga que usou a ArrayBufferpara criar uma união entre a Float64Arraye a Uint16Array, consulte o histórico de revisões desta resposta .

Patrick Roberts
fonte
Obrigado, é bom que isso funcione para 64 bits. Você pode me dizer alguma vantagem dessa resposta sobre a resposta de annan?
Barlop
2
Faixa muito maior? Ele trabalha para -(2**53)-1a 2**53-1em vez de apenas -(2**31)a 2**31-1como a resposta de Annan.
Patrick Roberts
Sim, essa é uma grande vantagem, eu entendo, e isso serve, embora seja um pouco mais de código, mas o que eu quis dizer foi: estou curioso para saber outras vantagens?
barlop
1
a partir de 2 ** 32 + 1 em diante, o último bit (mais à direita) é apagado quando deve ser definido.
precisa
1
Funciona quando a linha é: var expoente = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Lovro
15

Uma solução que eu consideraria adequada para 32 bits é o código no final desta resposta, que é de developer.mozilla.org (MDN), mas com algumas linhas adicionadas para A) formatação e B), verificando se o número está no intervalo.

Alguns sugeriram x.toString(2)que não funciona para negativos, apenas coloca um sinal de menos para eles, o que não é bom.

Fernando mencionou uma solução simples, (x>>>0).toString(2);que é boa para negativos, mas tem um pequeno problema quando x é positivo. Ele tem a saída começando com 1, que para números positivos não é o complemento adequado de 2s.

Qualquer pessoa que não entenda o fato de números positivos começando com 0 e números negativos com 1, em complemento 2s, pode verificar esse SO QnA em complemento 2s. O que é o "Complemento 2"?

Uma solução poderia envolver a adição de um 0 para números positivos, o que fiz em uma revisão anterior desta resposta. E pode-se aceitar algumas vezes ter um número de 33 bits, ou se pode garantir que o número a converter esteja dentro do intervalo - (2 ^ 31) <= x <2 ^ 31-1. Portanto, o número é sempre 32 bits. Mas, em vez de fazer isso, você pode usar esta solução no mozilla.org

A resposta e o código de Patrick são longos e aparentemente funcionam para 64 bits, mas tinham um bug que um comentarista encontrou e o comentarista corrigiu o bug de patrick, mas patrick possui um "número mágico" em seu código que ele não comentou e que possui. esquecido e patrick não entende mais completamente seu próprio código / por que ele funciona.

Annan tinha alguma terminologia incorreta e pouco clara, mas mencionou uma solução por developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators Isso funciona para números de 32 bits.

O código é bastante compacto, uma função de três linhas.

Mas eu adicionei um regex para formatar a saída em grupos de 8 bits. Baseado em Como imprimir um número com vírgulas como separadores de milhares em JavaScript (eu apenas o alterei de agrupá-lo em 3s da direita para a esquerda e adicionar vírgulas , para agrupar em 8s da direita para a esquerda e adicionar espaços )

E, enquanto o mozilla fez um comentário sobre o tamanho do nMask (o número alimentado) .. que ele deve estar dentro do alcance, eles não testaram ou lançaram um erro quando o número está fora do alcance, então eu acrescentou isso.

Não sei por que eles nomearam o parâmetro 'nMask', mas deixarei como está.

Referência: 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
fonte
8

Você pode escrever sua própria função que retorna uma matriz de bits. Exemplo de como converter número em bits

Divisor Dividendo bits / restante

2 9 1

2 4 | 0 0

2 2 0 0

~ 1 | ~

exemplo da linha acima: 2 * 4 = 8 e o restante é 1, então 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
}

Leia os restantes de baixo para cima. Dígito 1 no meio para cima.

supritshah1289
fonte
1
Btw, por que você em Math.floor(number%2)vez de number = Math.floor(number/2)?
Pacerier 17/02
1
O motivo é que o número% 2 não é igual ao número / 2. Estamos interessados ​​no restante, não no quociente.
Supritshah1289
0

Eu usei uma abordagem diferente para criar algo que faça isso. Decidi não usar esse código no meu projeto, mas pensei em deixá-lo em algum lugar relevante, caso seja útil para alguém.

  • Não usa troca de bits ou coerção de complemento de dois.
  • Você escolhe o número de bits que sai (ele verifica valores válidos de '8', '16', '32', mas suponho que você possa mudar isso)
  • Você escolhe se deve tratá-lo como um número inteiro assinado ou não assinado.
  • Ele verificará problemas de intervalo, dada a combinação de assinado / não assinado e número de bits, embora você queira melhorar o tratamento de erros.
  • Ele também possui a versão "reversa" da função que converte os bits novamente em int. Você precisará disso, pois provavelmente não há mais nada que possa interpretar essa saída: 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("---");

freios
fonte
-1

Mais uma alternativa

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));
Ivan Proskuryakov
fonte
Por favor, veja a resposta de Vincent e o comentário sobre ela, também se aplicaria à sua postagem
barlop
Foi o que foi postado no comentário de sua resposta, sem discordância e com o consentimento de outras pessoas: "Isso pode ser útil para estudar ciência da computação e ver como fazê-lo manualmente, para aprender sozinho, mas não é isso que eu Se você vai reinventar a roda fazendo isso manualmente, deve ser pelo menos com a vantagem do aumento da eficiência ou com alguma vantagem como o aumento no tamanho dos valores com os quais ele pode lidar. qualquer discussão sua afirmando essa vantagem lá ".
barlop 26/04
Além disso, sua solução falha completamente, faz com que os números positivos comecem com 1 e falhe completamente nos números negativos, e minha pergunta mencionou positiva ou negativa
barlop
Portanto, sua "resposta" está errada em muitos níveis. E você deve sempre revisar outras respostas antes de postar uma resposta
barlop 26/04
-2

Este é o meu código:

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();
Vincent William Rodriguez
fonte
3
Isso pode ser útil no estudo da ciência da computação para ver como fazê-lo manualmente, de modo a ensinar a si mesmo, mas não é isso que estou perguntando! Se você pretende reinventar a roda manualmente, deve ter pelo menos a vantagem de aumentar a eficiência ou alguma vantagem como o aumento no tamanho dos valores com os quais pode lidar. Não vejo nenhuma discussão sua afirmando essa vantagem lá.
barlop
-3

Essa é a solução. É bem simples, de fato

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.
        */
Brian
fonte
1
Essa solução já foi proposta várias vezes e, como comentado pelo OP em 30 de março de 2012 às 9:01, não funciona para números negativos.
Adrian W
@AdrianW Eu sugiro que voteie isso. Percebo que você não. O que é preciso para você rebaixar uma resposta então ?!
barlop