Come faccio a convertire un numero intero in binario in JavaScript?


299

Mi piacerebbe vedere numeri interi, positivi o negativi, in binario.

Un po 'come questa domanda , ma per JavaScript.


2
gli esempi a.toString (2) non sembrano funzionare per -1
barlop

1
È anche possibile convertire da binario a decimale: stackoverflow.com/questions/11103487/…
Anderson Green

E quando ho detto "in binario", potrebbe essere un po 'ambiguo. Intendo la rappresentazione della stringa di bit interna, che è il complemento a 2s, quindi i numeri positivi sarebbero nella base 2 e con uno 0 iniziale (e i numeri negativi non sarebbero scritti con un simbolo meno o con una rappresentazione della magnitudine del segno, ma come un funzione del loro eqivalente positivo)
barlop

Risposte:


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

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

È possibile utilizzare la Number.toString(2)funzione, ma presenta alcuni problemi nella rappresentazione di numeri negativi. Ad esempio, l' (-1).toString(2)output è "-1".

Per risolvere questo problema, è possibile utilizzare l'operatore bit a bit di spostamento a destra senza segno ( >>>) per forzare il numero su un numero intero senza segno.

Se corri (-1 >>> 0).toString(2), sposterai il tuo numero 0 bit a destra, il che non cambia il numero stesso ma verrà rappresentato come un numero intero senza segno. Il codice sopra verrà emesso "11111111111111111111111111111111"correttamente.

Questa domanda ha ulteriori spiegazioni.

-3 >>> 0 (shift logico destro) costringe i suoi argomenti a numeri interi senza segno, motivo per cui si ottiene la rappresentazione del complemento a due bit a 32 bit di -3.


7
Ecco la spiegazione
fernandosavio il

è passato un po 'di tempo da quando ho provato javascript ma provandolo qui w3schools.com/js/tryit.asp?filename=tryjs_output_alert con questo <script> window.alert ((- 3 >>> 0) .toString (2)); </script> sì, ha funzionato
barlop

1
toString (2) non funziona perché stai ricevendo l'input dal testo. Utilizzare questo: funzione decToBase (dec, base) {return parseInt (dec) .toString (base); } avviso (decToBase (dec, 2));
Magus,

Stai assumendo che l'input sia un testo, ma la funzione nella risposta prevede un numero intero ... Quindi, se l'input è un testo, convertilo in numero intero, usa il finto bit e il gioco è fatto
fernandosavio,

@Mago che sta ricevendo l'input dal testo ?!
barlop

207

Provare

num.toString(2);

Il 2 è la radice e può essere qualsiasi base tra 2 e 36

fonte qui

AGGIORNARE:

Funzionerà solo con numeri positivi, Javascript rappresenta numeri interi binari negativi nella notazione a due complementi. Ho fatto questa piccola funzione che dovrebbe fare il trucco, non l'ho testato correttamente:

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

Ho avuto qualche aiuto da qui


non funziona per -1. a = -1; document.write (Number (a.ToString (2))); visualizza -1
barlop

L'aggiornamento non sembra funzionare per numeri negativi ( -3ritorni 1). Inoltre credo che dec > 0dovrebbe essere dec >= 0, che dovrebbe almeno risolvere 0. Perché dec2Bin(0)restituisce 10.
Adam Merrifield,

Entrambi i casi nei commenti precedenti restituiscono il risultato corretto nella mia console Chrome - var a = -1; a.ToString (2); "-1" var a = -3; a.ToString (2); "-11"
Anmol Saraf,

@AnmolSaraf Capisco cosa intendi, e mentre colloquialmente quando le persone dicono ciò che è -5 in decimale, e la risposta è -5 Quando si tratta di numeri negativi in ​​binario, in un certo senso sì, potresti attaccare un segno meno lì quindi 5 è 101 e -5 è -101 ma poiché i computer non memorizzano i segni meno, rappresentano solo 1 e 0, quindi quando diciamo numeri negativi in ​​binario, intendiamo davvero mettere il numero negativo (segno meno incluso) in 1 e 0. Alcuni modi includono complemento 1, complemento 2 e "segno e grandezza". Quindi -101010101 o -0101010 non è ciò che le persone intendono con un numero negativo in binario.
barlop

Questo link può essere interessante per alcuni stackoverflow.com/questions/12337360/… , comunque, la tua risposta si contraddice, scrivi "Javascript rappresenta numeri interi binari negativi nella notazione del complemento a due". E il tuo codice dice "Qui potresti rappresentare il numero nel complimento 2s, ma questo non è ciò che JS usa come [motivo senza senso]" E non dai neanche un riferimento.
barlop

53

Il binario in "converti in binario" può riferirsi a tre cose principali. Il sistema numerico posizionale, la rappresentazione binaria in memoria o bittrings a 32 bit. (per bittring a 64 bit, vedere la risposta di Patrick Roberts )

1. Sistema numerico

(123456).toString(2)convertirà i numeri nel sistema numerico posizionale di base 2 . In questo sistema i numeri negativi sono scritti con segni meno proprio come in decimale.

2. Rappresentanza interna

La rappresentazione interna dei numeri è a virgola mobile a 64 bit e alcune limitazioni sono discusse in questa risposta . Non esiste un modo semplice per creare una rappresentazione di stringhe di bit in javascript né accedere a bit specifici.

3. Maschere e operatori bit a bit

MDN ha una buona panoramica di come funzionano gli operatori bit a bit. È importante sottolineare che:

Gli operatori bit a bit considerano i loro operandi come una sequenza di 32 bit (zero e uno)

Prima di applicare le operazioni, i numeri in virgola mobile a 64 bit vengono espressi in numeri interi con segno a 32 bit. Dopo che sono stati riconvertiti.

Ecco il codice di esempio MDN per convertire i numeri in stringhe a 32 bit.

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"

Qual è il vantaggio di usare questa funzione invece di usare un semplice Numero (num) .toString (2)?
Magus,

5
@Magus Penso di spiegare adeguatamente le differenze tra numeri e stringhe binarie. Una stringa binaria a 32 bit contiene sempre trentadue caratteri composti da "1" se "0". toString restituisce un numero effettivo rappresentato utilizzando i sistemi di numeri posizionali con la base specificata. Dipende dal motivo per cui vuoi che la stringa abbia significati molto diversi.
AnnanFay,

scusa, hai ragione. Ho saltato direttamente al codice.
Magus il

1
Si è verificato un problema con gli 0 iniziali utilizzando gli altri metodi pubblicati (in particolare su questo numero 536870912, i due zero iniziali vengono rimossi), ma questa soluzione lo ha gestito correttamente.
UberMouse il

@UberMouse sì, >>> presenta il problema 0 iniziale, accetterò questo.
barlop

43

Un modo semplice è solo ...

Number(42).toString(2);

// "101010"

24
Preferirei(42).toString(2)
Willem D'Haeseleer,

33
O ancora più breve42..toString(2)
kapex il

9
Le persone stanno lottando con questo. La risposta è corretta perché lancia l'input (42) su un numero intero e quella riga è necessaria. Se ottieni il tuo "numero" da un input di testo, toString (2) non funzionerebbe.
Magus,

4
@Kapep, amico, è geniale. Come lo sapevi?
Pacerier,

2
@BatuG. La sintassi per i numeri consente di omettere la parte dopo il separatore decimale. Puoi scrivere 1.che è uguale 1.0o solo 1(e allo stesso modo puoi anche omettere la parte prima e scrivere .5invece di 0.5). Quindi nell'esempio il primo punto è il separatore decimale che fa parte del numero e il secondo punto è l'operatore punto per chiamare il metodo su quel numero. Devi usare due punti (o racchiudere il numero tra parentesi) e non puoi semplicemente scrivere 42.toString(2)perché il parser vede il punto come separatore decimale e genera un errore a causa di un operatore punto mancante.
Kapex,

30

Questa risposta tenta di indirizzare gli input con un valore assoluto nell'intervallo 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


In JavaScript, i numeri sono memorizzati nella rappresentazione in virgola mobile a 64 bit , ma le operazioni bit a bit li costringono a numeri interi a 32 bit in formato complemento a due , quindi qualsiasi approccio che utilizza operazioni a bit limita l'intervallo di output a -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

Tuttavia, se si evitano operazioni bit a bit e la rappresentazione in virgola mobile a 64 bit viene preservata utilizzando solo operazioni matematiche, è possibile convertire in modo affidabile qualsiasi numero intero sicuro in notazione binaria del complemento a due bit a 64 bit estendendo il segno a 53 bit 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}

Per i browser più vecchi, esistono polyfill per le seguenti funzioni e valori:

Come bonus aggiuntivo, puoi supportare qualsiasi radix (2–36) se esegui la conversione del complemento a due per numeri negativi in ​​⌈64 / log 2 (radix) ⌉ cifre 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 sei interessato alla mia vecchia risposta che ha usato un ArrayBufferper creare un'unione tra una Float64Arraye una Uint16Array, fai riferimento alla cronologia delle revisioni di questa risposta .


Grazie, è positivo che funzioni a 64 bit. Puoi farmi sapere i vantaggi di questa risposta rispetto alla risposta di Annan?
barlop

2
Gamma molto più ampia? Funziona per -(2**53)-1a 2**53-1invece di -(2**31)a 2**31-1come la risposta di Annan.
Patrick Roberts,

Sì, questo è un grande vantaggio, lo capisco, e lo farà, anche se è un po 'più di codice, ma quello che intendevo dire era, sono curioso di sapere se ci fossero altri vantaggi?
barlop

1
da 2 ** 32 + 1 in poi, l'ultimo bit (più a destra) viene cancellato quando deve essere impostato.
Lovro,

1
Funziona quando la linea è: var exponent = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Lovro,

15

Una soluzione con cui andrei bene per 32 bit, è il codice alla fine di questa risposta, che proviene da developer.mozilla.org (MDN), ma con alcune righe aggiunte per la formattazione A) e B) verificando che il il numero è nell'intervallo.

Alcuni hanno suggerito x.toString(2)che non funziona per i negativi, attacca solo un segno meno lì per loro, il che non va bene.

Fernando ha menzionato una soluzione semplice (x>>>0).toString(2);che va bene per i negativi, ma ha un leggero problema quando x è positivo. Ha l'output che inizia con 1, che per i numeri positivi non è un complemento corretto per 2 secondi.

Chiunque non capisca il fatto di numeri positivi che iniziano con 0 e numeri negativi con 1, nel complemento 2s, potrebbe controllare questo QnA SO sul complemento 2s. Che cos'è il "complemento di 2"?

Una soluzione potrebbe comportare anteporre uno 0 per i numeri positivi, cosa che ho fatto in una precedente revisione di questa risposta. E a volte si potrebbe accettare di avere un numero di 33 bit, oppure si potrebbe assicurarsi che il numero da convertire sia compreso nell'intervallo - (2 ^ 31) <= x <2 ^ 31-1. Quindi il numero è sempre a 32 bit. Ma invece di farlo, puoi scegliere questa soluzione su mozilla.org

La risposta e il codice di Patrick sono lunghi e apparentemente funzionano a 64 bit, ma avevano un bug che un commentatore ha trovato e il commentatore ha corretto il bug di patrick, ma patrick ha un "numero magico" nel suo codice di cui non ha commentato e ha dimenticato e patrick non capisce più completamente il proprio codice / perché funziona.

Annan aveva una terminologia errata e poco chiara ma menzionava una soluzione di developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators Funziona con numeri a 32 bit.

Il codice è piuttosto compatto, una funzione di tre righe.

Ma ho aggiunto una regex per formattare l'output in gruppi di 8 bit. Basato su Come stampare un numero con virgole come migliaia di separatori in JavaScript (l'ho appena modificato dal raggruppamento in 3 secondi da destra a sinistra e l'aggiunta di virgole , al raggruppamento in 8 secondi da destra a sinistra e l'aggiunta di spazi )

E, mentre mozilla ha fatto un commento sulla dimensione di nMask (il numero inserito) .. che deve essere compreso nell'intervallo, non hanno testato o generato un errore quando il numero è fuori intervallo, quindi ho aggiunto quello.

Non sono sicuro del motivo per cui hanno chiamato il loro parametro 'nMask' ma lo lascerò così com'è.

Riferimento: 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"


8

È possibile scrivere la propria funzione che restituisce una matrice di bit. Esempio come convertire il numero in bit

divisore | dividendo | bit / rimanente

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 | ~

esempio della riga sopra: 2 * 4 = 8 e il resto è 1, quindi 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
}

Leggi i resti dal basso verso l'alto. Cifra 1 al centro verso l'alto.


1
A proposito, perché Math.floor(number%2)invece di number = Math.floor(number/2)?
Pacerier,

1
Il motivo è il numero% 2 non è uguale al numero / 2. Siamo interessati al resto non al quoziente.
supritshah1289,

0

Ho usato un approccio diverso per trovare qualcosa che lo facesse. Ho deciso di non utilizzare questo codice nel mio progetto, ma ho pensato di lasciarlo in un posto rilevante nel caso fosse utile per qualcuno.

  • Non utilizza la coercizione del bit shifting o del complemento a due.
  • Scegli il numero di bit che esce (controlla i valori validi di '8', '16', '32', ma suppongo che potresti cambiarlo)
  • Scegli se trattarlo come un intero con segno o senza segno.
  • Controllerà i problemi di intervallo data la combinazione di segno / non firmato e numero di bit, anche se vorrai migliorare la gestione degli errori.
  • Ha anche la versione "inversa" della funzione che converte i bit in int. Ne avrai bisogno poiché probabilmente non c'è nient'altro che interpreterà questo output: 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("---");


-1

Un'altra 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));

Si prega di vedere la risposta di Vincent e il suo commento, si applicherebbe anche al tuo post
barlop

Questo è ciò che è stato pubblicato nei commenti sulla sua risposta, senza disaccordo, e con un certo accordo da parte di altri, "Potrebbe essere utile per studiare informatica per vedere come farlo manualmente, in modo da insegnare a te stesso, ma non è quello che sto chiedendo! Se hai intenzione di reinventare la ruota facendola manualmente in quel modo, allora dovrebbe essere almeno con il vantaggio di una maggiore efficienza o qualche vantaggio come un aumento delle dimensioni dei valori che può far fronte. qualsiasi discussione da parte tua che dichiari tali vantaggi ".
barlop

Inoltre, la tua soluzione fallisce completamente, fa sì che i numeri positivi inizino con un 1 e fallisca completamente per i numeri negativi, e la mia domanda menzionata positiva o negativa
barlop

Quindi la tua "risposta" è sbagliata su molti livelli. E dovresti sempre rivedere le altre risposte prima di pubblicare una risposta
barlop

-2

Questo è il mio codice:

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
Potrebbe essere utile per studiare informatica per vedere come farlo manualmente, in modo da insegnare a te stesso, ma non è quello che ti chiedo! Se hai intenzione di reinventare la ruota facendola manualmente in quel modo, allora dovrebbe essere almeno con il vantaggio di una maggiore efficienza o qualche vantaggio come l'aumento della dimensione dei valori che può affrontare. Non vedo alcuna discussione da parte tua affermando che tale vantaggio lì.
barlop

-3

Questa è la soluzione È piuttosto semplice

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
Tale soluzione è già stata proposta molte volte e, come commentato dall'OP già il 30 marzo 12 alle 9:01, non funziona con numeri negativi.
Adrian W,

@AdrianW Suggerisco di sottovalutare questo. Ho notato che non l'hai fatto. Cosa ci vuole per votare una risposta allora ?!
barlop
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.