繁体   English   中英

如何在 JavaScript 中将整数转换为二进制?

[英]How do I convert an integer to binary in JavaScript?

我想以二进制形式查看整数,正数或负数。

很喜欢这个问题,但是对于 JavaScript。

 function dec2bin(dec) { return (dec >>> 0).toString(2); } console.log(dec2bin(1)); // 1 console.log(dec2bin(-1)); // 11111111111111111111111111111111 console.log(dec2bin(256)); // 100000000 console.log(dec2bin(-256)); // 11111111111111111111111100000000

您可以使用Number.toString(2)函数,但它在表示负数时会出现一些问题。 例如, (-1).toString(2)输出为"-1"

要解决此问题,您可以使用无符号右移位运算符 ( >>> ) 将您的数字强制为无符号整数。

如果您运行(-1 >>> 0).toString(2)您会将数字 0 向右移动,这不会更改数字本身,但它将表示为无符号整数。 上面的代码将正确输出"11111111111111111111111111111111"

这个问题有进一步的解释。

-3 >>> 0 (右逻辑移位)将其参数强制转换为无符号整数,这就是为什么您会得到 -3 的 32 位二进制补码表示。

尝试

num.toString(2);

2 是基数,可以是 2 到 36 之间的任何基数

来源这里

更新:

这仅适用于正数,Javascript 以二进制补码表示法表示负二进制整数。 我做了这个应该可以解决问题的小功能,但我没有正确测试它:

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

我从这里得到了一些帮助

一个简单的方法就是...

Number(42).toString(2);

// "101010"

“转换为二进制”中的二进制可以指三个主要内容。 位置数字系统,内存中的二进制表示或 32 位位串。 (对于 64 位位串,请参阅Patrick Roberts 的回答

1. 数制

(123456).toString(2)将数字转换为以 2 为底的位置数字系统 在这个系统中,负数用减号写成,就像十进制一样。

2. 内部代表

数字的内部表示是64 位浮点数,在这个答案中讨论了一些限制。 没有简单的方法可以在 javascript 中创建它的位串表示,也没有访问特定位的简单方法。

3. 掩码和位运算符

MDN 很好地概述了按位运算符的工作原理。 重要的:

按位运算符将其操作数视为32 位(零和一)的序列

在应用操作之前,将 64 位浮点数转换为 32 位有符号整数。 在他们被转换回来之后。

这是用于将数字转换为 32 位字符串的 MDN 示例代码。

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"

此答案尝试使用 2147483648 10 (2 31 ) – 9007199254740991 10 (2 53 -1) 范围内的绝对值来处理输入。


在 JavaScript 中,数字以64 位浮点表示形式存储,但按位运算将它们强制转换为二进制补码格式的32 位整数,因此任何使用按位运算的方法都将输出范围限制为 -2147483648 10 (-2 31 ) – 2147483647 10 (2 31 -1)。

但是,如果避免按位运算并仅使用数学运算保留 64 位浮点表示,我们可以通过对 53 位twosComplement进行符号扩展,将任何安全整数可靠地转换为 64 位二进制补码二进制表示法:

 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}

对于较旧的浏览器,polyfills 存在以下功能和值:

另外,如果您使用BigInt对 ⌈64 / log 2 (radix)⌉ 数字中的负数执行二进制补码转换,则可以支持任何基数 (2–36):

 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}

如果您对我使用ArrayBufferFloat64ArrayUint16Array之间创建联合的旧答案感兴趣,请参阅此答案的修订历史

我想采用的解决方案适用于 32 位,是此答案结尾的代码,来自 developer.mozilla.org(MDN),但添加了一些行用于 A)格式化和 B)检查数字在范围内。

一些人建议x.toString(2)不适用于负数,它只是在其中贴一个减号,这不好。

Fernando 提到了(x>>>0).toString(2); 这对于负数很好,但当 x 为正数时有一个小问题。 它的输出以 1 开头,对于正数,它不是正确的 2s 补码。

任何不了解 2s 补码中以 0 开头的正数和以 1 开头的负数这一事实的人都可以在 2s 补码上检查此 SO QnA。 什么是“2的补码”?

一个解决方案可能涉及为正数添加一个 0,我在此答案的早期版本中这样做了。 有时可以接受 33 位数字,或者可以确保要转换的数字在 -(2^31)<=x<2^31-1 范围内。 所以这个数字总是32位。 但是,您可以在 mozilla.org 上使用此解决方案,而不是这样做

帕特里克的答案和代码很长,显然适用于 64 位,但有一个评论者发现的错误,评论者修复了帕特里克的错误,但帕特里克在他的代码中有一些“幻数”,他没有评论并且有忘记了,帕特里克不再完全理解他自己的代码/它为什么起作用。

Annan 有一些不正确和不清楚的术语,但提到了 developer.mozilla.org 的解决方案

注意 - 旧链接https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators现在重定向到其他地方并且没有该内容但正确的旧链接,当archive.org 检索页面!,可在此处获得https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

那里的解决方案适用于 32 位数字。

代码非常紧凑,三行的函数。

但是我添加了一个正则表达式来格式化输出,以 8 位为一组。 基于如何在 JavaScript 中将逗号打印为千位分隔符(我只是将其修改为从右到左将其分组为3 秒并添加逗号,以从右到左分组为8 秒并添加空格

而且,虽然 Mozilla 对 nMask 的大小(输入的数字)发表了评论......它必须在范围内,但当数字超出范围时,他们没有测试或抛出错误,所以我已经补充说。

我不确定他们为什么将参数命名为“nMask”,但我会保持原样。

https://web.archive.org/web/20150315015832/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" //added further console.log example console.log(createBinaryString(2**31 -1)) //"01111111 11111111 11111111 11111111"

您可以编写自己的函数来返回位数组。 示例如何将数字转换为位

除数| 股息| 位/余数

2 | 9 | 1

2 | 4 | 0

2 | 2 | 0

~ | 1 |~

以上行的示例: 2 * 4 = 8 余数为 1 所以 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
}

从下到上阅读余数。 数字 1 在中间到顶部。

这就是我设法处理它的方式:

const decbin = nbr => {
  if(nbr < 0){
     nbr = 0xFFFFFFFF + nbr + 1
  }
  return parseInt(nbr, 10).toString(2)
};

从这个链接得到它: https ://locutus.io/php/math/decbin/

我们还可以计算正数或负数的二进制,如下所示:

 function toBinary(n){ let binary = ""; if (n < 0) { n = n >>> 0; } while(Math.ceil(n/2) > 0){ binary = n%2 + binary; n = Math.floor(n/2); } return binary; } console.log(toBinary(7)); console.log(toBinary(-7));

您可以使用递归解决方案:

 function intToBinary(number, res = "") { if (number < 1) if (res === "") return "0" else return res else return intToBinary(Math.floor(number / 2), number % 2 + res) } console.log(intToBinary(12)) console.log(intToBinary(546)) console.log(intToBinary(0)) console.log(intToBinary(125))
仅适用于正数。

我想以二进制形式查看整数,正数或负数。

这是一个老问题,我认为这里有很好的解决方案,但没有解释如何使用这些聪明的解决方案。

首先,我们需要了解一个数字可以是正数或负数。 此外,JavaScript 提供了一个值为9007199254740991MAX_SAFE_INTEGER常量。 该数字背后的原因是 JavaScript 使用IEEE 754中指定的双精度浮点格式数字,并且只能安全地表示-(2^53 - 1)2^53 - 1之间的整数。

所以,现在我们知道了数字“安全”的范围。 此外,JavaScript ES6 具有内置方法Number.isSafeInteger()来检查数字是否为安全整数。

从逻辑上讲,如果我们想将一个数字n表示为二进制,这个数字需要 53 位的长度,但为了更好地表示,我们使用 7 组 8 位 = 56 位,并根据其符号使用01填充左侧padStart函数。

接下来,我们需要处理正数和负数:正数将向左添加0 ,而负数将向左添加1 此外,负数需要二进制补码表示。 我们可以通过将Number.MAX_SAFE_INTEGER + 1添加到数字来轻松解决此问题。

例如,我们想将-3表示为二进制,假设Number.MAX_SAFE_INTEGER00000000 11111111 (255)那么Number.MAX_SAFE_INTEGER + 1将是00000001 00000000 (256) 现在让我们添加数字Number.MAX_SAFE_INTEGER + 1 - 3这将是00000000 11111101 (253)但正如我们所说,我们将用1填充左侧,例如11111111 11111101 (-3) ,这表示二进制的-3

另一种算法是我们将数字加1并像这样反转符号-(-3 + 1) = 2这将是00000000 00000010 (2) 现在我们像这样反转每一位11111111 11111101 (-3)再次我们有-3的二进制表示。

在这里,我们有这些算法的工作片段:

 function dec2binA(n) { if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer') if (n > 2**31) throw 'number too large. number should not be greater than 2**31' if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31' const bin = n < 0 ? Number.MAX_SAFE_INTEGER + 1 + n : n const signBit = n < 0 ? '1' : '0' return parseInt(bin, 10).toString(2) .padStart(56, signBit) .replace(/\B(?=(.{8})+(?!.))/g, ' ') } function dec2binB(n) { if (!Number.isSafeInteger(n)) throw new TypeError('n value must be a safe integer') if (n > 2**31) throw 'number too large. number should not be greater than 2**31' if (n < -1*(2**31)) throw 'number too far negative, number should not be lesser than 2**31' const bin = n < 0 ? -(1 + n) : n const signBit = n < 0 ? '1' : '0' return parseInt(bin, 10).toString(2) .replace(/[01]/g, d => +!+d) .padStart(56, signBit) .replace(/\B(?=(.{8})+(?!.))/g, ' ') } const a = -805306368 console.log(a) console.log('dec2binA:', dec2binA(a)) console.log('dec2binB:', dec2binB(a)) const b = -3 console.log(b) console.log('dec2binA:', dec2binA(b)) console.log('dec2binB:', dec2binB(b))

另一种选择

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

任何编程语言都可以实现逻辑的实际解决方案:

如果你确定它只是积极的:

var a = 0;
var n = 12; // your input
var m = 1;
while(n) {
    a = a + n%2*m;
    n = Math.floor(n/2);
    m = m*10;
}

console.log(n, ':', a) // 12 : 1100

如果可以消极或积极 -

(n >>> 0).toString(2)

我使用了一种不同的方法来解决这个问题。 我决定不在我的项目中使用这段代码,但我想我会把它留在相关的地方,以防它对某人有用。

  • 不使用位移位或二进制补码强制转换。
  • 您选择输出的位数(它检查“8”、“16”、“32”的有效值,但我想你可以改变它)
  • 您可以选择将其视为有符号整数还是无符号整数。
  • 考虑到有符号/无符号和位数的组合,它将检查范围问题,但您需要改进错误处理。
  • 它还具有将位转换回 int 的函数的“反向”版本。 您将需要它,因为可能没有其他东西可以解释此输出: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("---");

这是我使用的一种方法。 这是一种非常快速且简洁的方法,适用于整数。

如果需要,此方法也适用于 BigInts。 您只需将每个1更改为1n

// Assuming {num} is a whole number
function toBin(num){
    let str = "";
    do {
        str = `${num & 1}${str}`;
        num >>= 1;
    } while(num);
    return str
}

解释

这种方法在某种程度上遍历了数字的所有位,就好像它已经是一个二进制数一样。

它以空字符串开头,然后添加最后一位。 num & 1将返回数字的最后一位( 10 )。 num >>= 1然后删除最后一位并使倒数第二位成为新的最后一位。 重复该过程,直到已读取所有位。

当然,这是对实际情况的极端简化。 但这就是我概括它的方式。

这是我的代码:

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

这就是解决方案。 事实上它很简单

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.
        */

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM