Search code examples
javascripttheorynumber-formatting

How does base 10 number to base 2 number conversion work?


I'm trying to understand the following code, found in MDN and in an answer of this related question. (Tested in FF 30 only.)

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;
}
var p = createBinaryString(7);
console.log(p); //"00000000000000000000000000000111"

This one is on MDN, but how does this work - I'd appreciate any understandable explanation. I have basic knowledge of binary operators and know, that there is a .toString(2) method. But what does the String(nShifted >>> 31) part do exactly?

Here are better readable versions, but the first one does not work. Here I also would appreciate any suggestion about what I'm doing wrong. I can't see any difference to the second, working version.

var re = '';
var numb = 7;
var shiftBuf = numb;
for (var i = 0; i < 32; i++); {
   re += String(shiftBuf >>> 31);
   shiftBuf <<= 1;
}
console.log(re); //"0" 

var result = '';
var num = 7;
var shiftBuffer = num;
for (var i = 0; i < 32; i++) {
   result += String(shiftBuffer >>> 31);
   shiftBuffer <<= 1;
}
console.log(result); //"00000000000000000000000000000111"

Solution

  • The important assumption here is that the initial number is less then 2^32. In that case it's just retrieving a digit after digit in binary representation.

    re += String(shiftBuf >>> 31);
    shiftBuf <<= 1;
    

    The first line adds shiftBuf moved 31 places to the right to re, the second line moves shiftBuf to the left. So basically it just gets digits. Here's an example. If shiftBuf = 7; then in binary representation it is 111. Add missing zeros and you have

    00000000000000000000000000000111
    

    Step by step:

    [0] shiftBuf >>> 31 produces 0  // picks first digit if shiftBuf < 2^32
    [0] result is now "0"
    [0] shitBuffer <<= 1 produces 00000000000000000000000000001110
    
    [1] shiftBuf >>> 31 produces 0
    [1] result is now "00"
    [1] shitBuffer <<= 1 produces 00000000000000000000000000011100
    
    [2] shiftBuf >>> 31 produces 0
    [2] result is now "000"
    [2] shitBuffer <<= 1 produces 00000000000000000000000000111000
    
    ...
    
    [30] shiftBuf >>> 31 produces 1
    [30] result is now "0000000000000000000000000000011"
    [30] shitBuffer <<= 1 produces 10000000000000000000000000000000
    
    [31] shiftBuf >>> 31 produces 1
    [31] result is now "00000000000000000000000000000111"
    [31] shitBuffer <<= 1 produces 00000000000000000000000000000000
    

    As for your second question: the difference between these two codes is that in the first one you have for (var i = 0; i < 32; i++); (note the semicolon at the end). The code that follows (the one in brackets {}) does not run in a loop. It runs only once.