J'aimerais voir des nombres entiers, positifs ou négatifs, en binaire.
Un peu comme cette question , mais pour JavaScript.
Cette réponse tente de traiter les entiers avec des valeurs absolues comprises entre Number.MAX_SAFE_INTEGER
(ou 2**53-1
) et 2**31
. Les solutions actuelles ne traitent que les entiers signés sur 32 bits, mais cette solution générera le complément en deux 64 bits à l'aide de float64ToInt64Binary()
:
// IIFE to scope internal variables
var float64ToInt64Binary = (function () {
// create union
var flt64 = new Float64Array(1)
var uint16 = new Uint16Array(flt64.buffer)
// 2**53-1
var MAX_SAFE = 9007199254740991
// 2**31
var MAX_INT32 = 2147483648
function uint16ToBinary() {
var bin64 = ''
// generate padded binary string a Word at a time
for (var Word = 0; Word < 4; Word++) {
bin64 = uint16[Word].toString(2).padStart(16, 0) + bin64
}
return bin64
}
return function float64ToInt64Binary(number) {
// NaN would pass through Math.abs(number) > MAX_SAFE
if (!(Math.abs(number) <= MAX_SAFE)) {
throw new RangeError('Absolute value must be less than 2**53')
}
var sign = number < 0 ? 1 : 0
// shortcut using other answer for sufficiently small range
if (Math.abs(number) <= MAX_INT32) {
return (number >>> 0).toString(2).padStart(64, sign)
}
// little endian byte ordering
flt64[0] = number
// subtract bias from exponent bits
var exponent = ((uint16[3] & 0x7FF0) >> 4) - 1022
// encode implicit leading bit of mantissa
uint16[3] |= 0x10
// clear exponent and sign bit
uint16[3] &= 0x1F
// check sign bit
if (sign === 1) {
// apply two's complement
uint16[0] ^= 0xFFFF
uint16[1] ^= 0xFFFF
uint16[2] ^= 0xFFFF
uint16[3] ^= 0xFFFF
// propagate carry bit
for (var Word = 0; Word < 3 && uint16[Word] === 0xFFFF; Word++) {
// apply integer overflow
uint16[Word] = 0
}
// complete increment
uint16[Word]++
}
// only keep integer part of mantissa
var bin64 = uint16ToBinary().substr(11, Math.max(exponent, 0))
// sign-extend binary string
return bin64.padStart(64, sign)
}
})()
console.log('8')
console.log(float64ToInt64Binary(8))
console.log('-8')
console.log(float64ToInt64Binary(-8))
console.log('2**33-1')
console.log(float64ToInt64Binary(2**33-1))
console.log('-(2**33-1)')
console.log(float64ToInt64Binary(-(2**33-1)))
console.log('2**53-1')
console.log(float64ToInt64Binary(2**53-1))
console.log('-(2**53-1)')
console.log(float64ToInt64Binary(-(2**53-1)))
console.log('2**52')
console.log(float64ToInt64Binary(2**52))
console.log('-(2**52)')
console.log(float64ToInt64Binary(-(2**52)))
console.log('2**52+1')
console.log(float64ToInt64Binary(2**52+1))
console.log('-(2**52+1)')
console.log(float64ToInt64Binary(-(2**52+1)))
.as-console-wrapper {
max-height: 100% !important;
}
Cette réponse traite principalement du format à virgule flottante double précision IEEE-754 , illustré ici:
seee eeee eeee ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
[ uint16[3] ] [ uint16[2] ] [ uint16[1] ] [ uint16[0] ]
[ flt64[0] ]
little endian byte ordering
s = sign = uint16[3] >> 15
e = exponent = (uint16[3] & 0x7FF) >> 4
f = fraction
La solution consiste à créer une union entre un nombre à virgule flottante de 64 bits et un tableau d'entiers non signés de 16 bits dans un ordre d'octet peu significatif. Après avoir validé la plage d'entrée entière, il convertit l'entrée en un nombre à virgule flottante à double précision dans la mémoire tampon, puis utilise l'union pour obtenir un accès bit à la valeur et calcule la chaîne binaire sur la base des bits d'exposant et de fraction binaires non biaisés.
La solution est implémentée dans ECMAScript 5 pur sauf pour l’utilisation de String#padStart()
, qui a n polyfill disponible ici .
_function dec2bin(dec){
return (dec >>> 0).toString(2);
}
dec2bin(1); // 1
dec2bin(-1); // 11111111111111111111111111111111
dec2bin(256); // 100000000
dec2bin(-256); // 11111111111111111111111100000000
_
Vous pouvez utiliser la fonction Number.toString(2)
, mais la représentation de nombres négatifs pose quelques problèmes. Par exemple, _(-1).toString(2)
_ sortie est _"-1"
_.
Pour résoudre ce problème, vous pouvez utiliser l'opérateur de bits non signé de décalage à droite ( >>>
) pour contraindre votre nombre à un entier non signé.
Si vous exécutez _(-1 >>> 0).toString(2)
_, vous décalerez votre nombre 0 bits vers la droite, ce qui ne changera pas le nombre lui-même, mais il sera représenté par un entier non signé. Le code ci-dessus générera _"11111111111111111111111111111111"
_ correctement.
Cette question a plus d'explications.
_
-3 >>> 0
_ (décalage logique de droite) convertit ses arguments en entiers non signés, raison pour laquelle vous obtenez la représentation du complément à deux de 32 bits de -3.
Essayer
num.toString(2);
Le 2 est le radix et peut être n’importe quelle base entre 2 et 36
source ici
UPDATE:
Cela ne fonctionnera que pour les nombres positifs, Javascript représente des entiers binaires négatifs en notation à complément à deux. J'ai créé 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 https://stackoverflow.com/questions/10936600/javascript-decimal-to-binary-64-bit
*/
return (~dec).toString(2);
}
}
J'ai eu de l'aide de ici
Le binaire in 'convertir en binaire' peut faire référence à trois choses principales. Le système de numéro de position, la représentation binaire en mémoire ou les chaînes de bits 32 bits. (pour les chaînes de bits 64 bits, voir réponse de Patrick Roberts )
1. Système de numération
(123456).toString(2)
convertira les nombres en base 2 système de numération de position . Dans ce système, les nombres négatifs sont écrits avec des signes moins, tout comme en décimal.
2. Représentation interne
La représentation interne des nombres est virgule flottante 64 bits et certaines limitations sont décrites dans cette réponse . Il n'y a aucun moyen simple de créer une représentation sous forme de chaîne de bits en javascript, ni d'accéder à des bits spécifiques.
3. Masques et opérateurs au niveau des bits
MDN a un bon aperç du fonctionnement des opérateurs au niveau du bit. Important:
Les opérateurs au niveau des bits traitent leurs opérandes comme une séquence de 32 bits (zéros et uns)
Avant que les opérations ne soient appliquées, les nombres à virgule flottante 64 bits sont convertis en entiers signés 32 bits. Après qu'ils soient reconvertis.
Voici l'exemple de code MDN permettant de convertir des nombres en chaînes 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"
Un moyen simple est juste ...
Number(42).toString(2);
// "101010"
Remarque: le (x>>>0).toString(2);
de base présente un léger problème lorsque x est positif. J'ai un exemple de code à la fin de ma réponse qui corrige ce problème avec la méthode >>> tout en continuant d'utiliser >>>.
(-3>>>0).toString(2);
prints -3 in 2s complement.
1111111111101
Un exemple de travail
C:\>type n1.js
console.log( (-3 >>> 0).toString(2) );
C:\>
C:\>node n1.js
11111111111111111111111111111101
C:\>
Ceci dans la barre d'URL est une autre preuve rapide
javascript:alert((-3>>>0).toString(2))
Remarque: le résultat est très légèrement erroné, en ce sens qu'il commence toujours par un 1, ce qui est correct pour les nombres négatifs. Pour les nombres positifs, vous devez ajouter un 0 au début, afin que le résultat soit vraiment complémentaire de 2s. Ainsi, (8>>>0).toString(2)
produit 1000 qui n'est pas vraiment un complément 8 en 2, mais une valeur 0, ce qui en fait 01000, correspond au complément 8 en 2. En complément 2 correct, toute chaîne de bits commençant par 0 est> = 0, et toute chaîne de bits commençant par 1 est négative.
par exemple. cela contourne ce problème
// or x=-5 whatever number you want to view in binary
x=5;
if(x>0) prepend="0"; else prepend="";
alert(prepend+((x>>>0)).toString(2));
Les autres solutions sont celles d’Annan (bien que les explications et les définitions d’Annan soient pleines d’erreurs, il a un code qui produit le bon résultat) et la solution de Patrick.
Quiconque ne comprend pas le fait que les nombres positifs commencent par 0 et les nombres négatifs par 1, en complément à 2, peut vérifier ce complément SO QnA sur 2s. Qu'est-ce que le "Complément 2"?
Vous pouvez écrire votre propre fonction qui retourne un tableau de bits. Exemple comment convertir un nombre en bits
exemple de la 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
}
Lire les restes de bas en haut. Chiffre 1 au milieu en haut.
J'ai utilisé une approche différente pour proposer quelque chose qui fait cela. J'ai décidé de ne pas utiliser ce code dans mon projet, mais je pensais le laisser ailleurs, au cas où il serait utile à quelqu'un.
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("---");