¿Cómo convierto un entero a binario en JavaScript?

299

Me gustaría ver enteros, positivos o negativos, en binario.

Más bien como esta pregunta , pero para JavaScript.

barlop
fuente
2
los ejemplos de a.toString (2) no parecen funcionar para -1
barlop
1
También es posible convertir de binario a decimal: stackoverflow.com/questions/11103487/…
Anderson Green
Y cuando dije "en binario", eso puede ser un poco ambiguo. Me refiero a la representación interna de la cadena de bits, que es un complemento de 2s, por lo que los números positivos estarían en la base 2 y con un 0 inicial (y los números negativos no se escribirían con un símbolo menos o con una representación de magnitud de signo, sino como un función de su equivalente positivo)
barlop 05 de

Respuestas:

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

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

Puede usar la Number.toString(2)función, pero tiene algunos problemas al representar números negativos. Por ejemplo, la (-1).toString(2)salida es "-1".

Para solucionar este problema, puede usar el operador bit a la derecha sin signo ( >>>) para forzar su número a un entero sin signo.

Si ejecuta (-1 >>> 0).toString(2), desplazará su número 0 bits hacia la derecha, lo que no cambia el número en sí, pero se representará como un entero sin signo. El código anterior saldrá "11111111111111111111111111111111"correctamente.

Esta pregunta tiene más explicaciones.

-3 >>> 0 (desplazamiento lógico a la derecha) coacciona sus argumentos a enteros sin signo, razón por la cual obtiene la representación de complemento de dos de 32 bits de -3.

fernandosavio
fuente
77
Aquí está la explicación
fernandosavio
ha pasado un tiempo desde que probé javascript pero probándolo aquí w3schools.com/js/tryit.asp?filename=tryjs_output_alert con este <script> window.alert ((- 3 >>> 0) .toString (2)); </script> sí funcionó
barlop
1
toString (2) no funciona porque está recibiendo la entrada de texto. Use esto: función decToBase (dec, base) {return parseInt (dec) .toString (base); } alerta (decToBase (dec, 2));
Magus
Usted está asumiendo que la entrada es de texto, pero la función de la respuesta espera un número entero ... Por lo tanto, si la entrada es un texto que acaba de convertir a un entero, utilice el BitShift falso y se hace
fernandosavio
@Magus, ¿quién está recibiendo la entrada de texto?
barlop
207

Tratar

num.toString(2);

El 2 es la raíz y puede ser cualquier base entre 2 y 36

fuente aquí

ACTUALIZAR:

Esto solo funcionará para números positivos, Javascript representa enteros binarios negativos en notación de complemento a dos. Hice esta pequeña función que debería funcionar, no la he probado correctamente:

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

Tuve algo de ayuda de aquí

Manatok
fuente
no funciona para -1. a = -1; document.write (Number (a.toString (2))); muestra -1
barlop
La actualización todavía no parece funcionar para números negativos ( -3devoluciones 1). También creo que dec > 0debería ser dec >= 0, que al menos debería arreglar 0. Porque dec2Bin(0)devuelve 10.
Adam Merrifield
Ambos casos en los comentarios anteriores devuelven el resultado correcto en mi consola Chrome: var a = -1; a.toString (2); "-1" var a = -3; a.toString (2); "-11"
Anmol Saraf
@AnmolSaraf Entiendo lo que quieres decir, y mientras coloquialmente cuando la gente dice lo que es -5 en decimal, y la respuesta es -5 Cuando se trata de números negativos en binario, en cierto sentido, sí, podrías pegar un signo menos allí, entonces 5 es 101 y -5 es -101, pero dado que las computadoras no almacenan signos menos, solo representan 1s y 0s, por lo que cuando decimos números negativos en binario, realmente queremos decir poner el número negativo (signo menos incluido) en 1s y 0s. Algunas formas incluyen el complemento 1s, el complemento 2s y el 'signo y magnitud'. Entonces -101010101 o -0101010 no es lo que las personas quieren decir con un número negativo en binario.
barlop
Este enlace puede ser de interés para algunos stackoverflow.com/questions/12337360/… de todos modos, su respuesta se contradice, usted escribe "Javascript representa enteros binarios negativos en notación de complemento a dos". Y su código dice "Aquí podría representar el número en el cumplido 2s, pero esto no es lo que JS usa como [razón sin sentido]" Y tampoco da ninguna referencia.
barlop
53

El binario en 'convertir a binario' puede referirse a tres cosas principales. El sistema de números posicionales, la representación binaria en memoria o cadenas de bits de 32 bits. (para cadenas de bits de 64 bits, ver la respuesta de Patrick Roberts )

1. Sistema de numeración

(123456).toString(2)convertirá números al sistema de numeración posicional de base 2 . En este sistema, los números negativos se escriben con signos menos al igual que en decimal.

2. Representación interna

La representación interna de los números es de coma flotante de 64 bits y en esta respuesta se analizan algunas limitaciones . No hay una manera fácil de crear una representación de cadena de bits de esto en JavaScript ni acceder a bits específicos.

3. Máscaras y operadores bit a bit

MDN tiene una buena visión general de cómo funcionan los operadores bit a bit. En tono rimbombante:

Los operadores bit a bit tratan sus operandos como una secuencia de 32 bits (ceros y unos)

Antes de aplicar las operaciones, los números de coma flotante de 64 bits se convierten en enteros con signo de 32 bits. Después de que se convierten de nuevo.

Aquí está el código de ejemplo MDN para convertir números en cadenas 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
fuente
¿Cuál es la ventaja de usar esta función en lugar de usar un simple Number (num) .toString (2)?
Magus
55
@ Magus Creo que explico adecuadamente las diferencias entre los números y las cadenas binarias. Una cadena binaria de 32 bits siempre tiene treinta y dos caracteres de largo compuestos por "1" y "0". toString devuelve un número real representado usando los sistemas de números posicionales con la base dada. Depende de por qué quieres la cadena, tienen significados muy diferentes.
AnnanFay
lo siento, tienes razon Salté directamente al código.
Magus
1
Tuve un problema con los ceros a la izquierda utilizando los otros métodos publicados (específicamente en este número 536870912, se eliminan los dos ceros a la izquierda), pero esta solución lo manejó correctamente.
UberMouse
@UberMouse, sí, el >>> tiene el problema principal de 0s, aceptaré este.
barlop
43

Una forma simple es solo ...

Number(42).toString(2);

// "101010"
anuncio rees
fuente
24
Preferiría(42).toString(2)
Willem D'Haeseleer
33
O incluso más corto42..toString(2)
kapex
99
La gente está luchando con esto. La respuesta es correcta porque convierte la entrada (42) en un número entero y esa línea es necesaria. Si obtiene su 'número' de una entrada de texto, toString (2) no funcionaría.
Magus
44
@Kapep, amigo, eso es genial. ¿Cómo supiste sobre eso?
Pacerier
2
@BatuG. La sintaxis para los números le permite omitir la parte después del separador decimal. Puede escribir 1.cuál es igual 1.0o solo 1(y de manera similar también puede omitir la parte anterior y escribir en .5lugar de 0.5). Entonces, en el ejemplo, el primer punto es el separador decimal que es parte del número y el segundo punto es el operador de punto para llamar al método en ese número. Debe usar dos puntos (o ajustar el número entre paréntesis) y no puede simplemente escribir 42.toString(2)porque el analizador ve el punto como separador decimal y arroja un error debido a que falta un operador de punto.
kapex
30

Esta respuesta intenta direccionar entradas con un valor absoluto en el rango de 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


En JavaScript, los números se almacenan en representación de coma flotante de 64 bits , pero las operaciones bit a bit los obligan a números enteros de 32 bits en formato de complemento a dos , por lo que cualquier enfoque que utilice operaciones bit a bit restringe el rango de salida a -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

Sin embargo, si se evitan las operaciones bit a bit y la representación de coma flotante de 64 bits se conserva utilizando solo operaciones matemáticas, podemos convertir de manera confiable cualquier entero seguro a la notación binaria del complemento a dos de 64 bits al extender el signo 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 antiguos, existen polyfills para las siguientes funciones y valores:

Como una ventaja adicional, puede admitir cualquier raíz (2–36) si realiza la conversión del complemento de dos para números negativos en ⌈64 / log 2 (raíz) ⌉ dígitos 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}

Si está interesado en mi respuesta anterior que usaba un ArrayBufferpara crear una unión entre ay Float64Arraya Uint16Array, consulte el historial de revisión de esta respuesta .

Patrick Roberts
fuente
Gracias, es bueno que esto funcione para 64 bits. ¿Me puede decir alguna ventaja de esta respuesta sobre la respuesta de annan?
barlop
2
Rango mucho mayor? Se trabaja para -(2**53)-1que 2**53-1en lugar de limitarse -(2**31)a 2**31-1como respuesta de Annan.
Patrick Roberts
Sí, eso es una gran ventaja, lo entiendo, y eso servirá, aunque es un poco más de código, pero lo que quise decir fue, ¿tengo curiosidad si hay otras ventajas?
barlop
1
desde 2 ** 32 + 1 en adelante, el último bit (más a la derecha) se borra cuando se debe establecer
Lovro
1
Funciona cuando la línea es: var exponent = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Lovro
15

Una solución con la que estaría bien para 32 bits es el código al final de esta respuesta, que es de developer.mozilla.org (MDN), pero con algunas líneas agregadas para el formato A) y B) verificar que el El número está en el rango.

Algunos sugirieron x.toString(2)que no funciona para los negativos, simplemente coloca un signo menos allí para ellos, lo que no es bueno.

Fernando mencionó una solución simple (x>>>0).toString(2);que está bien para los negativos, pero tiene un pequeño problema cuando x es positivo. Tiene la salida que comienza con 1, que para números positivos no es el complemento de 2s adecuado.

Cualquiera que no entienda el hecho de que los números positivos comienzan con 0 y los números negativos con 1, en el complemento de 2s, puede verificar este SO QnA en el complemento de 2s. ¿Qué es el "Complemento de 2"?

Una solución podría implicar anteponer un 0 para números positivos, lo que hice en una revisión anterior de esta respuesta. Y uno podría aceptar a veces tener un número de 33 bits, o uno podría asegurarse de que el número a convertir esté dentro del rango - (2 ^ 31) <= x <2 ^ 31-1. Entonces el número siempre es de 32 bits. Pero en lugar de hacer eso, puedes usar esta solución en mozilla.org

La respuesta y el código de Patrick son largos y aparentemente funcionan para 64 bits, pero tenía un error que encontró un comentarista, y el comentarista corrigió el error de Patrick, pero Patrick tiene algún "número mágico" en su código sobre el que no comentó y olvidado y patrick ya no entiende completamente su propio código / por qué funciona.

Annan tenía una terminología incorrecta y poco clara, pero mencionó una solución de developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators Esto funciona para números de 32 bits.

El código es bastante compacto, una función de tres líneas.

Pero he agregado una expresión regular para formatear la salida en grupos de 8 bits. Basado en Cómo imprimir un número con comas como separadores de miles en JavaScript (solo lo modifiqué desde agruparlo en 3s de derecha a izquierda y agregar comas , hasta agruparlo en 8s de derecha a izquierda y agregar espacios )

Y, aunque Mozilla hizo un comentario sobre el tamaño de nMask (el número introducido) ... que tiene que estar dentro del rango, no probaron ni arrojaron un error cuando el número está fuera del rango, así que he agregó eso.

No estoy seguro de por qué nombraron su parámetro 'nMask', pero lo dejaré como está.

Referencia: 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
fuente
8

Puede escribir su propia función que devuelve una matriz de bits. Ejemplo de cómo convertir números a bits

Divisor | Dividendo | bits / resto

2 | 9 | 1

2 | 4 | 0 0

2 | 2 | 0 0

~ | 1 | ~

ejemplo de la línea anterior: 2 * 4 = 8 y el resto es 1, entonces 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
}

Lea los restos de abajo hacia arriba. Dígito 1 en el medio hacia arriba.

supritshah1289
fuente
1
Por cierto, ¿por qué en Math.floor(number%2)lugar de number = Math.floor(number/2)?
Pacerier
1
La razón es que el número% 2 no es igual al número / 2. Estamos interesados ​​en el resto no cociente.
supritshah1289
0

Utilicé un enfoque diferente para llegar a algo que haga esto. Decidí no usar este código en mi proyecto, pero pensé que lo dejaría en algún lugar relevante en caso de que sea útil para alguien.

  • No utiliza desplazamiento de bits o coerción de complemento a dos.
  • Usted elige la cantidad de bits que sale (verifica los valores válidos de '8', '16', '32', pero supongo que podría cambiar eso)
  • Usted elige si tratarlo como un entero con signo o sin signo.
  • Verificará los problemas de rango dada la combinación de firmado / no firmado y número de bits, aunque querrá mejorar el manejo de errores.
  • También tiene la versión "inversa" de la función que convierte los bits de nuevo a int. Lo necesitará, ya que probablemente no haya nada más que interprete esta salida: 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("---");

frenos
fuente
-1

Una alternativa mas

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
fuente
Consulte la respuesta de Vincent y el comentario al respecto, también se aplicaría a su publicación
barlop
Esto es lo que se publicó en el comentario sobre su respuesta, sin desacuerdo, y con el acuerdo de otros, "Eso puede ser útil para estudiar ciencias de la computación para ver cómo hacerlo manualmente, para que te enseñes a ti mismo, pero eso no es lo que yo Estoy preguntando! Si va a reinventar la rueda haciéndolo manualmente de esa manera, entonces debería ser al menos con la ventaja de una mayor eficiencia o alguna ventaja como el aumento en el tamaño de los valores que puede manejar. No veo cualquier discusión tuya que indique tal ventaja allí ".
barlop
Además, su solución falla por completo, hace que los números positivos comiencen con un 1 y falla por completo para los números negativos, y mi pregunta menciona positivo o negativo
barlop
Entonces su "respuesta" es incorrecta en muchos niveles. Y siempre debe revisar otras respuestas antes de publicar una respuesta
barlop
-2

Este es mi 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
fuente
3
Eso puede ser útil para estudiar ciencias de la computación para ver cómo hacerlo de forma manual, para aprender por sí mismo, ¡pero eso no es lo que estoy preguntando! Si va a reinventar la rueda haciéndolo manualmente de esa manera, entonces debería ser al menos con la ventaja de una mayor eficiencia o alguna ventaja como el aumento en el tamaño de los valores con los que puede hacer frente. No veo ninguna discusión tuya que indique tal ventaja allí.
barlop
-3

Esta es la solución Es bastante simple de hecho

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
fuente
1
Esa solución ya se ha propuesto muchas veces y, como comentó OP ya el 30 de marzo de 12 a las 9:01, no funciona para números negativos.
Adrian W
@AdrianW Sugiero que desestimes esto. Me doy cuenta de que no lo has hecho. ¡¿Qué se necesita para que rechaces una respuesta entonces ?!
barlop