javascriptnumbers

How do I convert an integer to binary in JavaScript?


I’d like to see integers, positive or negative, in binary.

Rather like this question, but for JavaScript.


Solution

  • A solution i'd go with that's fine for 32-bits, is the code the end of this answer, which is from developer.mozilla.org(MDN), but with some lines added for A)formatting and B)checking that the number is in range.

    Some suggested x.toString(2) which doesn't work for negatives, it just sticks a minus sign in there for them, which is no good.

    Fernando mentioned a simple solution of (x>>>0).toString(2); which is fine for negatives, but has a slight issue when x is positive. It has the output starting with 1, which for positive numbers isn't proper 2s complement.

    Anybody that doesn't understand the fact of positive numbers starting with 0 and negative numbers with 1, in 2s complement, could check this SO QnA on 2s complement. What is “two's complement”?

    Another way of showing the issue with Fernando's answer is this. Let's say we want 5 in binary. In 2s complement, it's 0101. Fernando's answer would give num>>>0 in this case 5>>>0 which outputs 101. Now if we put that into an online calcualtor that converts 2s complement into decimal, we see that 101 is actually -3. https://www.compscilib.com/calculate/twos-complement?variation=twos-complement-to-decimal In 2s complement, 101 and 111101 represent the same number, a negative number. That being, -3. Not positive 5.

    A solution could involve prepending a 0 for positive numbers, which I did in an earlier revision of this answer. And one could accept sometimes having a 33bit number, or one could make sure that the number to convert is within range -(2^31)<=x<2^31-1. So the number is always 32bits. But rather than do that, you can go with this solution on mozilla.org

    Patrick's answer and code is long and apparently works for 64-bit, but had a bug that a commenter found, and the commenter fixed patrick's bug, but patrick has some "magic number" in his code that he didn't comment about and has forgotten about and patrick no longer fully understands his own code / why it works.

    Annan had some incorrect and unclear terminology but mentioned a solution by developer.mozilla.org

    Note- the old link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators now redirects elsewhere and doesn't have that content but the proper old link , which comes up when archive.org retrieves pages!, is available here https://web.archive.org/web/20150315015832/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

    The solution there works for 32-bit numbers.

    The code is pretty compact, a function of three lines.

    But I have added a regex to format the output in groups of 8 bits. Based on How to format a number with commas as thousands separators? (I just amended it from grouping it in 3s right to left and adding commas, to grouping in 8s right to left, and adding spaces)

    And, while mozilla made a comment about the size of nMask(the number fed in)..that it has to be in range, they didn't test for or throw an error when the number is out of range, so i've added that.

    Regarding why they named their parameter 'nMask', I wasn't sure but commenter Magne mentioned that it "might be because the integer is treated as a bitmask, and nMask then refers to multiple masks (a set of one or more masks, joined into one). See section "Automate Mask Creation" at that Mozille bitwise operators link.

    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"