Comment convertir un entier en binaire en JavaScript?

299

J'aimerais voir des entiers, positifs ou négatifs, en binaire.

Plutôt comme cette question , mais pour JavaScript.

barlop
la source
2
les exemples a.toString (2) ne semblent pas fonctionner pour -1
barlop
1
Il est également possible de convertir du binaire en décimal: stackoverflow.com/questions/11103487/…
Anderson Green
Et quand j'ai dit "en binaire", cela peut être un peu ambigu. Je veux dire la représentation de la chaîne de bits interne, qui est un complément de 2, donc les nombres positifs seraient dans la base 2, et avec un 0 en tête (et les nombres négatifs ne seraient pas écrits avec un symbole moins ou avec une représentation de l'amplitude du signe, mais comme fonction de leur équivalent positif)
barlop

Réponses:

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

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

Vous pouvez utiliser la Number.toString(2)fonction, mais elle a quelques problèmes lors de la représentation des nombres négatifs. Par exemple, la (-1).toString(2)sortie est "-1".

Pour résoudre ce problème, vous pouvez utiliser l'opérateur au niveau du bit de décalage à droite non signé ( >>>) pour contraindre votre numéro à un entier non signé.

Si vous exécutez, (-1 >>> 0).toString(2)vous décalerez votre nombre de 0 bits vers la droite, ce qui ne change pas le nombre lui-même mais il sera représenté comme un entier non signé. Le code ci-dessus sortira "11111111111111111111111111111111"correctement.

Cette question a une explication supplémentaire.

-3 >>> 0 (décalage logique vers la droite) contraint ses arguments à des entiers non signés, c'est pourquoi vous obtenez la représentation du complément à 32 bits de -3.

fernandosavio
la source
7
Voici l'explication
fernandosavio
cela fait un moment que je n'ai pas essayé javascript mais je l'ai essayé ici w3schools.com/js/tryit.asp?filename=tryjs_output_alert avec ce <script> window.alert ((- 3 >>> 0) .toString (2)); </script> ouais ça a marché
barlop
1
toString (2) ne fonctionne pas car vous obtenez l'entrée du texte. Utilisez ceci: function decToBase (dec, base) {return parseInt (dec) .toString (base); } alert (decToBase (déc, 2));
Magus
Vous supposez que l'entrée est du texte, mais la fonction dans la réponse attend un entier ... Donc, si l'entrée est un texte, convertissez-le simplement en entier, utilisez le faux décalage de bits et c'est fait
fernandosavio
@Magus qui obtient la saisie du texte?!
barlop
207

Essayer

num.toString(2);

Le 2 est le radix et peut être n'importe quelle base entre 2 et 36

source ici

METTRE À JOUR:

Cela ne fonctionnera que pour les nombres positifs, Javascript représente des entiers binaires négatifs en notation à complément à deux. J'ai fait cette petite fonction qui devrait faire l'affaire, je ne l'ai pas testée correctement:

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

J'ai eu de l'aide d' ici

Manatok
la source
ne fonctionne pas pour -1. a = -1; document.write (Number (a.toString (2))); affiche -1
barlop
La mise à jour ne semble toujours pas fonctionner pour les nombres négatifs ( -3retours 1). Je pense aussi que cela dec > 0devrait être dec >= 0, ce qui devrait au moins fixer 0. Parce que les dec2Bin(0)retours 10.
Adam Merrifield
Les deux cas dans les commentaires ci-dessus renvoient un résultat correct dans ma console chrome - var a = -1; a.toString (2); "-1" var a = -3; a.toString (2); "-11"
Anmol Saraf
@AnmolSaraf Je vois ce que tu veux dire, et bien que familièrement quand les gens disent ce qui est -5 en décimal, et la réponse est -5 En ce qui concerne les nombres négatifs en binaire, dans un sens ouais tu pourrais coller un signe moins là donc 5 est 101 et -5 est -101, mais comme les ordinateurs ne stockent pas les signes moins, ils représentent simplement les 1 et les 0, donc quand nous disons des nombres négatifs en binaire, nous voulons vraiment dire mettre le nombre négatif (signe moins inclus) en 1 et 0. Certains moyens incluent le complément 1, le complément 2 et le signe et l'ampleur. Donc -101010101 ou -0101010 n'est pas ce que les gens entendent par un nombre négatif en binaire.
barlop du
Ce lien peut être intéressant pour certains stackoverflow.com/questions/12337360/… de toute façon, votre réponse se contredit, vous écrivez "Javascript représente des nombres entiers binaires négatifs en notation à deux compléments." Et votre code dit "Ici, vous pourriez représenter le nombre dans le compliment 2s mais ce n'est pas ce que JS utilise comme [raison absurde]" Et vous ne donnez aucune référence non plus.
barlop
53

Le binaire dans 'convertir en binaire' peut se référer à trois choses principales. Le système de nombres positionnels, la représentation binaire en mémoire ou les chaînes de bits 32 bits. (pour les chaînes de bits 64 bits, voir la réponse de Patrick Roberts )

1. Système de numérotation

(123456).toString(2)convertira les nombres en système de chiffres positionnels de base 2 . Dans ce système, les nombres négatifs sont écrits avec des signes négatifs comme en décimal.

2. Représentation interne

La représentation interne des nombres est une virgule flottante de 64 bits et certaines limitations sont discutées dans cette réponse . Il n'y a pas de moyen facile de créer une représentation de chaîne de bits de cela en javascript ni d'accéder à des bits spécifiques.

3. Masques et opérateurs au niveau du bit

MDN a une bonne vue d' ensemble du fonctionnement des opérateurs au niveau du bit. Surtout:

Les opérateurs au niveau du bit traitent leurs opérandes comme une séquence de 32 bits (zéros et uns)

Avant d'appliquer les opérations, les nombres à virgule flottante 64 bits sont convertis en entiers signés 32 bits. Une fois qu'ils sont reconvertis.

Voici l'exemple de code MDN pour convertir des nombres en chaînes 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
la source
Quel est l'avantage d'utiliser cette fonction au lieu d'utiliser un simple Number (num) .toString (2)?
Magus
5
@Magus Je pense que j'explique correctement les différences entre les chiffres et les chaînes binaires. Une chaîne binaire de 32 bits comprend toujours trente-deux caractères composés de «1» et de «0». toString renvoie un nombre réel représenté à l'aide des systèmes de numérotation positionnels avec la base donnée. Cela dépend de la raison pour laquelle vous voulez la chaîne, ils ont des significations très différentes.
AnnanFay
désolé, vous avez raison. J'ai sauté directement sur le code.
Magus
1
Nous avons eu un problème avec les premiers 0 à l'aide des autres méthodes publiées (en particulier sur ce numéro 536870912, les deux zéros principaux sont supprimés), mais cette solution l'a géré correctement.
UberMouse
@UberMouse ouais le >>> a le principal problème de 0, j'accepterai celui-ci.
barlop
43

Un moyen simple est juste ...

Number(42).toString(2);

// "101010"
annonce rees
la source
24
Je préférerais(42).toString(2)
Willem D'Haeseleer
33
Ou encore plus court42..toString(2)
kapex
9
Les gens sont aux prises avec cela. La réponse est correcte car elle convertit l'entrée (42) en un entier et cette ligne est nécessaire. Si vous obtenez votre «numéro» à partir d'une entrée de texte, la chaîne toString (2) ne fonctionnera pas.
Magus
4
@Kapep, Mec c'est du génie. Comment saviez-vous cela?
Pacerier
2
@BatuG. La syntaxe des nombres vous permet d'omettre la partie après le séparateur décimal. Vous pouvez écrire 1.ce qui est identique 1.0ou juste 1(et de même, vous pouvez également omettre la partie avant et écrire à la .5place de 0.5). Ainsi, dans l'exemple, le premier point est le séparateur décimal qui fait partie du nombre et le deuxième point est l'opérateur de point pour appeler la méthode sur ce nombre. Vous devez utiliser deux points (ou encapsuler le nombre entre parenthèses) et ne pouvez pas simplement écrire 42.toString(2)car l'analyseur voit le point comme séparateur décimal et renvoie une erreur en raison d'un opérateur de point manquant.
kapex
30

Cette réponse tente d'adresser les entrées avec une valeur absolue dans la plage de 2147483648 10 (2 31 ) - 9007199254740991 10 (2 53 -1).


En JavaScript, les nombres sont stockés dans une représentation en virgule flottante 64 bits , mais les opérations au niveau du bit les contraignent à des entiers 32 bits au format complément à deux , de sorte que toute approche qui utilise des opérations au niveau du bit limite la plage de sortie à -2147483648 10 (-2 31 ) - 2147483647 10 (2 31 -1).

Cependant, si les opérations au niveau du bit sont évitées et que la représentation en virgule flottante 64 bits est préservée en utilisant uniquement des opérations mathématiques, nous pouvons convertir de manière fiable tout entier sûr en notation binaire complémentaire à deux bits 64 bits en étendant les 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}

Pour les navigateurs plus anciens, des polyfills existent pour les fonctions et valeurs suivantes:

En prime, vous pouvez prendre en charge n'importe quel radix (2–36) si vous effectuez la conversion du complément à deux pour les nombres négatifs en chiffres ⌈64 / log 2 (radix) ⌉ en utilisant 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 vous êtes intéressé par mon ancienne réponse qui utilisait an ArrayBufferpour créer une union entre a Float64Arrayet a Uint16Array, veuillez vous référer à l' historique de révision de cette réponse .

Patrick Roberts
la source
Merci, c'est bien que cela fonctionne pour 64 bits. Pouvez-vous me faire part des avantages de cette réponse par rapport à la réponse d'Annan?
barlop
2
Gamme beaucoup plus large? Il travaille pour -(2**53)-1au 2**53-1lieu de simplement -(2**31)à 2**31-1comme la réponse de annan.
Patrick Roberts
Oui, c'est un gros avantage, j'obtiens cela, et cela fera l'affaire, bien que ce soit un peu plus de code, mais ce que je voulais dire était, je suis curieux s'il y a d'autres avantages?
barlop
1
à partir de 2 ** 32 + 1, le dernier bit (le plus à droite) est effacé lorsqu'il doit être défini.
Lovro
1
Fonctionne lorsque la ligne est: var exponent = ((uint16 [3] & 0x7FF0) >> 4) - 1023 + 1;
Lovro
15

Une solution avec laquelle j'irais bien pour 32 bits, est le code à la fin de cette réponse, qui est de developer.mozilla.org (MDN), mais avec quelques lignes ajoutées pour A) le formatage et B) en vérifiant que le le nombre est dans la plage.

Certains ont suggéré x.toString(2)que cela ne fonctionne pas pour les négatifs, il colle simplement un signe moins pour eux, ce qui n'est pas bon.

Fernando a mentionné une solution simple (x>>>0).toString(2);qui convient aux négatifs, mais a un léger problème lorsque x est positif. Il a la sortie commençant par 1, ce qui pour les nombres positifs n'est pas le bon complément à 2.

Quiconque ne comprend pas le fait de nombres positifs commençant par 0 et de nombres négatifs avec 1, en complément 2s, pourrait vérifier ce SO QnA sur complément 2s. Qu'est-ce que le «complément 2»?

Une solution pourrait consister à ajouter un 0 pour les nombres positifs, ce que j'ai fait dans une révision précédente de cette réponse. Et on pourrait accepter d'avoir parfois un nombre 33 bits, ou on pourrait s'assurer que le nombre à convertir est dans la plage - (2 ^ 31) <= x <2 ^ 31-1. Le nombre est donc toujours de 32 bits. Mais plutôt que de le faire, vous pouvez opter pour cette solution sur mozilla.org

La réponse et le code de Patrick sont longs et fonctionnent apparemment pour 64 bits, mais il y avait un bogue trouvé par un commentateur et le commentateur a corrigé le bogue de patrick, mais patrick a un "numéro magique" dans son code qu'il n'a pas commenté et a oublié et patrick ne comprend plus pleinement son propre code / pourquoi il fonctionne.

Annan avait une terminologie incorrecte et peu claire mais a mentionné une solution par developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators Cela fonctionne pour les nombres 32 bits.

Le code est assez compact, une fonction de trois lignes.

Mais j'ai ajouté une expression régulière pour formater la sortie en groupes de 8 bits. Basé sur Comment imprimer un nombre avec des virgules en tant que milliers de séparateurs en JavaScript (je viens de le modifier en le regroupant en 3 secondes de droite à gauche et en ajoutant des virgules , en le regroupant en 8 secondes de droite à gauche et en ajoutant des espaces )

Et, alors que mozilla a fait un commentaire sur la taille de nMask (le nombre introduit) ... qu'il doit être dans la plage, ils n'ont pas testé ou jeté une erreur lorsque le nombre est hors plage, donc j'ai ajouté cela.

Je ne sais pas pourquoi ils ont nommé leur paramètre 'nMask' mais je laisserai cela tel quel.

Référence: 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
la source
8

Vous pouvez écrire votre propre fonction qui renvoie un tableau de bits. Exemple comment convertir un nombre en bits

Diviseur | Dividende | bits / reste

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 | ~

exemple de ligne ci-dessus: 2 * 4 = 8 et le reste est 1 donc 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
}

Lisez les restes de bas en haut. Chiffre 1 du milieu vers le haut.

supritshah1289
la source
1
BTW, pourquoi avez - vous au Math.floor(number%2)lieu de number = Math.floor(number/2)?
Pacerier
1
La raison en est que le nombre% 2 n'est pas égal au nombre / 2. Nous sommes intéressés par le reste et non par le quotient.
supritshah1289
0

J'ai utilisé une approche différente pour trouver quelque chose qui fait cela. J'ai décidé de ne pas utiliser ce code dans mon projet, mais j'ai pensé le laisser dans un endroit pertinent au cas où il serait utile pour quelqu'un.

  • N'utilise pas le décalage de bits ou la contrainte de complément à deux.
  • Vous choisissez le nombre de bits qui sort (il vérifie les valeurs valides de '8', '16', '32', mais je suppose que vous pouvez changer cela)
  • Vous choisissez de le traiter comme un entier signé ou non signé.
  • Il vérifiera les problèmes de plage compte tenu de la combinaison de signé / non signé et du nombre de bits, bien que vous souhaitiez améliorer la gestion des erreurs.
  • Il a également la version "inverse" de la fonction qui convertit les bits en entier. Vous en aurez besoin car il n'y a probablement rien d'autre qui interprétera cette sortie: 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("---");

freins
la source
-1

Encore une alternative

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
la source
S'il vous plaît voir la réponse de Vincent et le commentaire à ce sujet, cela s'appliquerait également à votre message
barlop
C'est ce qui a été posté en commentaire de sa réponse, sans désaccord, et avec un certain accord des autres, "Cela peut être utile pour étudier l'informatique pour voir comment le faire manuellement, afin de vous enseigner, mais ce n'est pas ce que je si vous allez réinventer la roue en la faisant manuellement comme ça, alors cela devrait être au moins avec l'avantage d'une efficacité accrue ou un avantage comme l'augmentation de la taille des valeurs auxquelles elle peut faire face. Je ne vois pas toute discussion de votre part indiquant un tel avantage là-bas. "
barlop le
De plus, votre solution échoue complètement, elle fait commencer les nombres positifs par un 1 et échoue complètement pour les nombres négatifs, et ma question mentionnée positive ou négative
barlop
Votre "réponse" est donc fausse à plusieurs niveaux. Et vous devriez toujours revoir les autres réponses avant de poster une réponse
barlop
-2

Voici mon code:

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
la source
3
Cela peut être utile pour étudier l'informatique pour voir comment le faire manuellement, afin de vous enseigner, mais ce n'est pas ce que je demande! Si vous allez réinventer la roue en la faisant manuellement comme ça, alors cela devrait être au moins avec l'avantage d'une efficacité accrue ou d'un avantage comme l'augmentation de la taille des valeurs auxquelles elle peut faire face. Je ne vois aucune discussion de votre part affirmant un tel avantage.
barlop
-3

Voilà la solution. C'est assez simple en fait

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
la source
1
Cette solution a déjà été proposée à plusieurs reprises et, comme l'a déjà fait remarquer OP le 30 mars 2012 à 9h01, ne fonctionne pas pour les nombres négatifs.
Adrian W
@AdrianW Je suggère de voter contre cela. Je remarque que non. Que vous faut-il alors pour voter contre une réponse?!
barlop