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

506

我希望看到以二进制形式表示的整数,可以是正数或负数。

就像这个问题一样,但是针对JavaScript。


5
a.toString(2) 的例子似乎对于 -1 无法正常工作。 - barlop
1
还可以将二进制转换为十进制:https://dev59.com/xGgu5IYBdhLWcg3wv5im - Anderson Green
当我说“用二进制表示”时,这可能有点模糊。我指的是内部位字符串表示,它是2s补码,因此正数将以基数2表示,并附带前导0(负数不会用减号符号或符号大小表示法写出,而是作为其正等价物的函数)。 - barlop
在JavaScript中,二进制中的负零实际上是什么?它只能以1的补码表示吗?通常表示为所有二进制1。-> 111111111.... 不确定有多少个。此参考文献将32位数字的二进制表示形式-0表示为1后跟31个零。- https://en.wikipedia.org/wiki/Signed_zero - JoePythonKing
@JoePythonKing 你说的“它只能是1s complement吗?”是什么意思?你来自英国,也许你可以用更好的英语写。你可以查一下 1s complement 或 2s complement 中的 -1。计算机倾向于使用 2s complement 而不是 1s complement,但从一个转换到另一个并不难。还有一些其他的表示方法。至于负数中有多少个1,在例如 2s complement 中,这并不重要,对于1s complement 也可能不重要。这取决于你有多少位来存储这个数字! - barlop
显示剩余6条评论
17个回答

2

一个实际的解决方案,逻辑可以由任何编程语言实现:

如果你确定它只是正数:

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)

你甚至没有读到问题的第一行,它说了负数也要考虑。你的解决方案对负数不起作用。 - barlop
@barlop 你应该尊重理想的事情,而不是你正在寻找的。JS是一种松散的语言,你知道的。你可以轻松地通过(n >>> 0).toString(2)来实现。 - Yadab Sd
1
尝试阅读其他答案,而不是发布一个没有回答问题(没有解决负数)的答案,然后调整您的答案并复制在另一个答案中提到的解决方案,以解决负数问题。顺便说一句,MDN也有一个解决方案,但所有这些都在其他答案中提到,所以您在这里没有添加任何内容。 - barlop
@barlop,那你应该搜索类似的答案,而不是提问... - Yadab Sd
你在说什么?没有人问过你任何问题。而且这个问题在你回答之前很久就已经被解决了。 - barlop

1
我想看到二进制中的整数,可以是正数或负数。
这是一个古老的问题,我认为这里有非常好的解决方案,但没有关于这些聪明的解决方案使用的说明。
首先,我们需要理解一个数字可以是正数或负数。 此外,JavaScript 提供了一个 MAX_SAFE_INTEGER 常量,它的值为 9007199254740991。这个数字背后的原因是 JavaScript 使用 IEEE 754 规定的双精度浮点格式数字,并且只能安全地表示介于 - (2^53-1) 和 2^53-1 之间的整数。
所以,现在我们知道了数字“安全”的范围。此外,JavaScript ES6 还具有内置方法 Number.isSafeInteger() 来检查一个数字是否为安全整数。
逻辑上,如果我们想将一个数字 n 表示为二进制,则需要 53 位长度,但为了更好地表示,让我们使用 7 组 8 位 = 56 位,并根据其符号使用 padStart 函数在左侧填充 0 或 1。
接下来,我们需要处理正数和负数:正数将在左侧添加 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))


0

另一种选择

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

-1

我采用了一种不同的方法来实现这个功能。虽然我决定不在我的项目中使用这段代码,但我认为我应该把它留在相关的地方,以防对某人有用。

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


你的测试数据不会失败吗?很明显,-128不是00000000。 - barlop
@barlop,有符号数据类型int8的范围是从-128(00000000)到127(11111111),这正是我想要的。我的需求不需要与另一个方案互操作。 - braks
如果在你的表示中-128全部为零,那么你将如何表示0? - barlop
我相信,只要你用心去想,你一定能够搞明白它。 - braks
看,-128 不应该是全部为 000000,你完全错了。而且你关于有符号整数的声明 -128 (00000000) 到 127 (11111111) 是编造的,完全错误的。 - barlop

-1

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

如果您想要,这种方法也适用于 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 然后移除最后一位,并将倒数第二位变为新的最后一位。该过程重复进行,直到读取完所有位数。

当然,这只是对实际情况的极度简化。但这是我对其的概括。


你的第一句话说“.toString(2)可能是你最好的选择。”-- 现在试着读问题的第一个评论。你会发现它只适用于正数。再试着阅读所有其他提到.toString(2)问题的答案。至于你的函数,它很有趣,你应该说明它只适用于正数,还是正负数都适用。 - 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在2012年3月30日9:01已经评论过的那样,对于负数是不起作用的。 - Adrian W
1
@AdrianW 我建议你给这个回答点个踩。我注意到你还没有这么做。那么,你需要什么才能给一个回答点个踩呢?! - barlop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接