Eu gostaria de ver números inteiros, positivos ou negativos, em binário.
Um pouco como esta pergunta , mas para JavaScript.
Eu gostaria de ver números inteiros, positivos ou negativos, em binário.
Um pouco como esta pergunta , mas para JavaScript.
Respostas:
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.
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
-3
retornos 1
). Também acredito que dec > 0
deveria ser dec >= 0
, que deveria pelo menos consertar 0. Porque dec2Bin(0)
retorna 10
.
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"
Uma maneira simples é apenas ...
Number(42).toString(2);
// "101010"
(42).toString(2)
42..toString(2)
1.
que é igual 1.0
ou apenas 1
(e da mesma forma também pode omitir a parte anterior e escrever em .5
vez 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.
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 ArrayBuffer
para criar uma união entre a Float64Array
e a Uint16Array
, consulte o histórico de revisões desta resposta .
-(2**53)-1
a 2**53-1
em vez de apenas -(2**31)
a 2**31-1
como a resposta de Annan.
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"
Você pode escrever sua própria função que retorna uma matriz de bits. Exemplo de como converter número em bits
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.
Math.floor(number%2)
vez de number = Math.floor(number/2)
?
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.
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("---");
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));
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();
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.
*/