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


299

我希望看到二进制的正整数或负整数。

而是像这个问题,但对于JavaScript。


2
a.toString(2)示例似乎不适用于-1
barlop 2012年

1
它也可以转换成二进制为十进制:stackoverflow.com/questions/11103487/...
安德森格林

当我说“二进制”时,可能有点含糊。我的意思是内部位字符串表示形式,它是2s的补码,因此正数应以2为底,前导0,(负数不会用减号或符号幅度表示,而是用正等价的功能)
barlop

Answers:


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

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

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

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

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

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

-3 >>> 0 (正确的逻辑移位)将其参数强制为无符号整数,这就是为什么要获得-3的32位二进制补码表示的原因。


7
是解释
fernandosavio

已经有一段时间了,因为我尝试了javascript,但是在这里尝试了w3schools.com/js/tryit.asp?filename=tryjs_output_alert 并带有<script> window.alert((-3 >>> 0).toString(2)); </ SCRIPT>是它的工作
barlop

1
toString(2)不起作用,因为您正在从文本获取输入。使用此函数:函数decToBase(dec,base){return parseInt(dec).toString(base); } alert(decToBase(dec,2));
Magus

您假设输入是文本,但是答案中的函数需要一个整数...因此,如果输入是文本,则只需将其转换为整数,然后使用伪造的bitshift即可完成
fernandosavio

@Magus谁正在从文本中获取输入?
barlop 2015年

207

尝试

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 /programming/10936600/javascript-decimal-to-binary-64-bit 
        */
        return (~dec).toString(2);
    }
}

我从这里得到了一些帮助


不适用于-1。a = -1; document.write(Number(a.toString(2))); 显示-1
barlop 2012年

对于负数(-3return 1),更新似乎仍然不起作用。我也相信dec > 0应该是dec >= 0,至少应该固定为0。因为dec2Bin(0)return 10
亚当·梅里菲尔德

以上注释中的两种情况都在我的Chrome控制台中返回正确的结果-var a = -1; a.toString(2); “ -1” var a = -3; a.toString(2); “ -11”
Anmol Saraf 2014年

@AnmolSaraf我明白了你的意思,而口语中,当人们说十进制为-5时,答案是-5当涉及二进制负数时,在某种意义上,你可以在其中贴减号,所以5是101和-5是-101,但是由于计算机不存储减号,因此它们仅表示1和0,因此当我们用二进制表示负数时,实际上是指将负数(包括减号)放在1和0中。一些方式包括1s补码,2s补码和“符号和大小”。所以-101010101或-0101010并不是人们用二进制负数表示的意思。
barlop 2015年

无论如何,此链接可能对某些stackoverflow.com/questions/12337360/很有用。您的回答与之相反,您写道:“ Javascript用二进制补码表示负的二进制整数。” 并且您的代码说:“在这里您可以用2秒的恭维来表示数字,但这不是JS用作[废话]的原因”,并且您也没有提供参考。
barlop

53

“转换为二进制”中的二进制可以涉及三个主要方面。位置编号系统,内存中的二进制表示形式或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"

使用此函数而不是使用简单的Number(num).toString(2)有什么好处?
Magus

5
@Magus我想我已经充分解释了数字和二进制字符串之间的区别。32位二进制字符串始终是32个字符,由“ 1”和“ 0”组成。toString返回使用具有给定基数的位置数字系统表示的实际数字。这取决于您为什么想要字符串,它们的含义非常不同。
AnnanFay 2015年

对不起,你是对的。我直接跳到代码。
Magus

1
使用其他已发布方法的前导0出现了问题(特别是在此编号536870912上,两个前导零被删除了),但是此解决方案正确处理了它。
UberMouse 2015年

@UberMouse是的>>>具有领先的0问题,我将接受这一问题。
barlop

43

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

Number(42).toString(2);

// "101010"

24
我宁愿(42).toString(2)
威廉D'Haeseleer

33
甚至更短42..toString(2)
kapex

9
人们为此苦苦挣扎。答案是正确的,因为它将输入(42)强制转换为整数,并且需要该行。如果从文本输入中获取“数字”,则toString(2)将不起作用。
Magus

4
@ Kapep,Dude是个天才。您怎么知道的?
Pacerier '17

2
@BatuG。数字的语法允许您省略小数点分隔符之后的部分。您可以编写1.与之相同1.0或相同的内容1(类似地,您也可以省略之前的部分并.5代替编写0.5)。因此,在该示例中,第一个点是小数点分隔符,它是数字的一部分,第二个点是用于在该数字上调用方法的点运算符。您必须使用两个点(或将数字括在括号中),并且不能只写,42.toString(2)因为解析器将点视为小数点分隔符,并且由于缺少点运算符而引发错误。
kapex

30

此答案尝试使用绝对值在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:

作为额外的奖励,你可以支持任意基数(2-36),如果您在⌈64执行二进制补码转换为负数/日志2使用(基数)⌉位数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}

如果您对我以前使用ArrayBuffer来在a Float64Array和a 之间创建并集的答案感兴趣Uint16Array,请参考该答案的修订历史记录


谢谢,它可以在64bit上使用。。您能让我知道这个答案比annan答案的优点吗?
barlop

2
更大的范围?它适用于-(2**53)-12**53-1,而不是只-(2**31)2**31-1像安南的答案。
Patrick Roberts

是的,这是一个很大的优势,我明白了,而且可以做到,尽管它需要很多代码,但是我的意思是,我想知道是否还有其他优势?
barlop

1
从2 ** 32 + 1开始,应设置最后一位(最右边)。
罗夫罗

1
当行为时工作:var exponent =((uint16 [3]&0x7FF0)>> 4)-1023 +1;
罗夫罗

15

我认为适合32位的解决方案是此答案结尾的代码,该代码来自developer.mozilla.org(MDN),但添加了几行用于A)格式设置和B)检查数字在范围内。

有些人建议x.toString(2)对负数无效,它只是在负数上加减号,这是不好的。

费尔南多(Fernando)提到了一个简单的解决方案,(x>>>0).toString(2);该方法适用于负数,但是当x为正数时会有一个小问题。它的输出以1开头,对于正数来说,这是不正确的2s补码。

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

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

帕特里克(Patrick)的答案和代码很长,而且显然适用于64位,但是有一个评论者发现的错误,并且评论者修复了帕特里克(bug)的错误,但是帕特里克在他的代码中有一些“不可思议的数字”,他没有对此发表评论并且拥有被遗忘的帕特里克不再完全了解自己的代码/代码为什么有效。

安南的术语有误和不清楚,但提到了developer.mozilla.org https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators的解决方案。 此方法适用于32位数字。

该代码非常紧凑,具有三行功能。

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

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

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

参考:https : //developer.mozilla.org/zh-CN/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

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

除数| 股利| 位数/余数

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。


1
顺便说一句,为什么你Math.floor(number%2)代替number = Math.floor(number/2)
Pacerier '17

1
原因是数字%2不等于数字/ 2。我们对余数而不是商数感兴趣。
supritshah1289

0

我使用了不同的方法来完成此任务。我决定不在我的项目中使用此代码,但我认为我会将其保留在适当的位置,以防对某人有用。

  • 不使用移位或二进制补码强制。
  • 您选择输出的位数(它会检查有效值'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("---");


-1

另一种选择

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

请参阅文森特的回答及其评论,它也适用于您的发帖
barlop

这是他对他的回答的评论,没有分歧,也得到了其他人的同意。我要问!如果您要像这样手动地改造轮子,那么它至少应该具有提高效率的优势或诸如它可以处理的值的大小增加之类的优势。您的任何讨论都指出了这种优势。”
barlop

此外,您的解决方案完全失败,它使正数以1开头,而对负数完全失败,并且我的问题提到正数或负数
barlop

因此,您的“答案”在许多层面上都是错误的。并且您应该始终在发布答案之前查看其他答案
barlop

-2

这是我的代码:

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
这对于学习计算机科学以了解如何手动进行以示教,可能很有用,但这不是我要的!如果您要像这样手动地改造轮子,那么它至少应该具有提高效率的优势,或者具有诸如可以应对的数值的增加之类的优势。我看不到您有任何讨论说明在那里有这样的优势。
barlop

-3

这是解决方案。其实很简单

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
该解决方案已经提出了很多次,并且正如OP在12年3月30日9:01所评论的那样,不适用于负数。
阿德里安W

@AdrianW我建议对此投票。我注意到你还没有。那么,您对投票的否决有什么要求?
barlop
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.