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

IT技术 javascript numbers
2021-01-17 11:13:05

我想看到二进制的整数,正数或负数。

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

6个回答

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 位二进制补码表示。

您假设输入是文本,但答案中的函数需要一个整数...因此,如果输入是文本,只需将其转换为整数,使用假位移即可完成
2021-03-19 11:13:05
@Magus 谁从文本中获取输入?!
2021-03-26 11:13:05
是解释
2021-04-07 11:13:05
自从我尝试 javascript 以来已经有一段时间了,但是在这里尝试w3schools.com/js/tryit.asp?filename=tryjs_output_alert 和这个 <script> window.alert((-3 >>> 0).toString(2)); </script> 是的,它奏效了
2021-04-07 11:13:05
toString(2) 不起作用,因为您从文本中获取输入。使用这个: function decToBase(dec, base){ return parseInt(dec).toString(base); } 警报(decToBase(dec, 2));
2021-04-11 11:13:05

尝试

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

我从这里得到了一些帮助

不适用于 -1。a=-1; document.write(Number(a.toString(2))); 显示 -1
2021-03-17 11:13:05
以上评论中的两种情况都在我的 chrome 控制台中返回了正确的结果 - var a = -1; a.toString(2); “-1” var a = -3; a.toString(2); “-11”
2021-03-22 11:13:05
更新似乎仍然不适用于负数(-3返回1)。我也相信dec > 0应该是dec >= 0,至少应该修复 0。因为dec2Bin(0)返回10
2021-03-23 11:13:05
@AnmolSaaf 我明白你的意思,虽然当人们说十进制是 -5 时,答案是 -5 当谈到二进制的负数时,从某种意义上说,你可以在那里贴一个减号,所以 5 是101 和 -5 是 -101 但由于计算机不存储减号,它们只表示 1 和 0,所以当我们用二进制表示负数时,我们真正的意思是将负数(包括减号)放入 1 和 0 中。一些方法包括 1s 补码、2s 补码和“符号和幅度”。所以 -101010101 或 -0101010 不是人们所说的二进制负数。
2021-04-03 11:13:05
这个链接可能对某些stackoverflow.com/questions/12337360/感兴趣……无论如何,你的答案自相矛盾,你写“Javascript 用二进制补码表示负二进制整数”。你的代码说“在这里你可以用 2 秒的赞美来表示这个数字,但这不是 JS 用作[废话原因]”你也没有给出任何参考。
2021-04-08 11:13:05

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

Number(42).toString(2);

// "101010"
@Kapep,伙计,那是天才。你是怎么知道的?
2021-03-16 11:13:05
或者更短 42..toString(2)
2021-03-19 11:13:05
人们正在为此苦苦挣扎。答案是正确的,因为它将输入 (42) 转换为整数并且需要该行。如果您从文本输入中获取“数字”,则 toString(2) 将不起作用。
2021-03-28 11:13:05
我会选择 (42).toString(2)
2021-03-30 11:13:05
@BatuG。数字的语法允许您省略小数点分隔符之后的部分。您可以写1.which is the same as 1.0or just 1(同样,您也可以省略之前的部分并用.5代替0.5)。所以在这个例子中,第一个点是小数点分隔符,它是数字的一部分,第二个点是用于调用该数字方法的点运算符。您必须使用两个点(或将数字括在括号中)并且不能只写,42.toString(2)因为解析器将点视为小数点分隔符并由于缺少点运算符而引发错误。
2021-04-09 11:13:05

“转换为二进制”中的二进制可以指三个主要的东西。位置数字系统,内存中的二进制表示或 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"
@UberMouse 是的 >>> 有前导 0 问题,我会接受这个问题。
2021-03-16 11:13:05
使用其他发布的方法存在前导 0 的问题(特别是在这个数字 536870912 上,两个前导零被删除),但该解决方案正确处理了它。
2021-03-21 11:13:05
对不起,你是对的。我直接跳到代码。
2021-03-25 11:13:05
@Magus 我想我充分解释了数字和二进制字符串之间的区别。一个 32 位的二进制字符串总是由 32 个字符组成,由“1”和“0”组成。toString 返回使用具有给定基数的位置数字系统表示实际数字。这取决于为什么想要这个字符串,它们有非常不同的含义。
2021-03-27 11:13:05
使用这个函数而不是使用简单的 Number(num).toString(2) 有什么好处?
2021-04-02 11:13:05

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


在JavaScript中,号码被存储在64位浮点表示,但按位操作强迫他们到32位整数2的补码格式,所以它使用按位操作的任何方法限制输出的范围,以-2147483648 10(-2 31) – 2147483647 10 (2 31 -1)。

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

对于较旧的浏览器,存在以下函数和值的 polyfill:

作为额外的好处,如果您使用 ⌈64 / log 2 (radix) ⌉ 数字对负数执行二进制补码转换,则可以支持任何基数 (2–36) 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}

如果您对我使用 anArrayBuffer在 aFloat64Array和 a之间创建联合的旧答案感兴趣Uint16Array,请参阅此答案的修订历史记录

范围更大?它适用于-(2**53)-12**53-1,而不是只-(2**31)2**31-1像安南的答案。
2021-03-15 11:13:05
谢谢,这适用于 64 位很好。你能告诉我这个答案比 annan 的答案有什么优势吗?
2021-03-21 11:13:05
当行为: var exponent = ((uint16[3] & 0x7FF0) >> 4) - 1023 + 1;
2021-04-07 11:13:05
是的,这是一个很大的优势,我明白了,而且会这样做,尽管代码要多一些,但我的意思是,我很好奇是否还有其他优势?
2021-04-08 11:13:05
从 2**32+1 开始,最后(最右边)位在应该设置时被清除。
2021-04-08 11:13:05