- Power
23
Convert Decimal to Binary in JavaScript
What you’ll learn
- How division by two and remainders yield binary digits from right to left.
- Why you must handle zero and why the first implementation prints the array backwards.
- An MSB-first bit walk for
n >>> 0(32-bit unsigned view), a live preview, and links to the inverse tutorial.
Overview
Binary uses powers of two. To express a nonnegative decimal integer in base two, repeatedly divide by 2 and record remainders 0 or 1; read those bits from last generated to first for MSB-first output.
Two programs
Remainder stack in an array (classic), then bit scan MSB-first with >>>.
Live preview
Nonnegative safe integers; mirrors (n >>> 0).toString(2) for the 32-bit unsigned view.
Inverse
Pair with binary to decimal for a full interview story.
Prerequisites
Integer division and modulo, arrays, for loops, and optional bitwise operators (>>>, &).
console.log,Number.isSafeInteger, andn >>> 0for unsigned 32-bit coercion.- Why
Number#toString(2)is handy for checks, but interviews still want the manual loops.
Decimal to binary
Each binary digit (bit) is a coefficient on a power of two. Converting a nonnegative integer n collects those bits by peeling parity: n % 2 is the least significant bit, then n = Math.floor(n / 2) shifts right in value.
Example: 15 = 8 + 4 + 2 + 1 = 1·23 + 1·22 + 1·21 + 1·20, written 11112.
Division algorithm
For n ≥ 0, define b0 = n mod 2, n1 = ⌊n/2⌋, then b1 = n1 mod 2, and so on until the quotient is 0. The sequence bk…b0 (reversed index) is the binary expansion of n.
1515 = 2·7 + 1, 7 = 2·3 + 1, 3 = 2·1 + 1, 1 = 2·0 + 1 → bits from LSB up: 1 1 1 1 → 1111.
Intuition
- Sum
4 + 1
Takeaway: each division step answers “odd or even?” at the current scale—that is the next bit.
Live preview
Nonnegative integers in the JavaScript safe range. Uses Number#toString(2) for a quick binary string.
Algorithm (remainder method)
Goal: print bits of nonnegative n in MSB-first order.
Special case n == 0
Print a single 0 and stop (the pure while (n > 0) loop prints nothing otherwise).
Collect bits
While n > 0: push n % 2, then n = Math.floor(n / 2).
Print reversed
Emit stored bits from last pushed down to first.
📜 Pseudocode
function printBinaryFromDecimal(n): // n ≥ 0
if n = 0:
output "0"; return
bits ← empty list
while n > 0:
append (n mod 2) to bits
n ← floor(n / 2)
print bits in reverse orderDivide by two with reverse print
Same structure as the reference, with an explicit zero branch. Uses n >>> 0 so inputs match a 32-bit unsigned view (like unsigned int in C).
function decimalToBinary(decimalNumber) {
const binaryDigits = [];
let n = decimalNumber >>> 0;
if (n === 0) {
console.log("Binary equivalent: 0");
return;
}
while (n > 0) {
binaryDigits.push(n % 2);
n = Math.floor(n / 2);
}
let line = "Binary equivalent: ";
for (let j = binaryDigits.length - 1; j >= 0; j--) {
line += String(binaryDigits[j]);
}
console.log(line);
}
const decimalNumber = 15 >>> 0;
decimalToBinary(decimalNumber);
decimalToBinary(0);Explanation
>>> 0 coerces to unsigned 32-bit, avoiding sign surprises while dividing by two.
for (let j = binaryDigits.length - 1; j >= 0; j--)MSB first. The last remainder pushed is the highest bit of the original value.
MSB-to-LSB with a bit scan
No reversal buffer: scan from bit 31 down to 0 on n >>> 0, skip leading zeros unless the value is 0. Uses (u >>> b) & 1 so we never build 1 << 31 as a signed mask.
function printBinaryMsb32(n) {
const u = n >>> 0;
if (u === 0) {
return "0";
}
let started = false;
let out = "";
for (let b = 31; b >= 0; b--) {
const bit = (u >>> b) & 1;
if (bit || started) {
out += bit ? "1" : "0";
started = true;
}
}
return out;
}
console.log("15 as binary: " + printBinaryMsb32(15));
console.log("64 as binary: " + printBinaryMsb32(64));Explanation
The started flag suppresses leading zeros; the first 1 begins the meaningful prefix.
(u >>> b) & 1Unsigned shift. Reads bit b without shifting a 1 into the sign bit of a signed 32-bit pattern.
Optimization
Find MSB once. For u > 0, start at bit 31 - Math.clz32(u) instead of scanning all 32 positions (Math.clz32 counts leading zeros on a 32-bit value).
Recursive print. Print Math.floor(n/2) first then n % 2 to emit MSB-first without storage (mind recursion depth for huge types).
Interview: mention n==0, >>> 0 for bit view, and inverse conversion.
❓ FAQ
🔄 Input / output examples
Example 1 uses 15 and 0; Example 2 shows 15 and 64.
| Decimal | Binary (minimal) |
|---|---|
0 | 0 |
1 | 1 |
15 | 1111 |
64 | 1000000 |
Edge cases and pitfalls
Signed division with negative n does not implement “binary string of absolute value”; pick n >>> 0 or document two's complement.
n == 0
Must print 0; the naive remainder loop alone prints an empty line.
Fixed 8 vs minimal
Hardware often wants padded width (00001111); interview questions should state padding rules.
1 << 31 on signed 32-bit
In JavaScript bitwise ops are 32-bit signed; 1 << 31 is negative. Prefer (u >>> b) & 1 or unsigned typed arrays when testing masks.
Binary to decimal
See the paired tutorial for Horner / digit peel when the input is a bit string.
⏱️ Time and space complexity
| Approach | Time | Extra space |
|---|---|---|
| Remainder + array | O(log n) bits | O(log n) digits stored |
| 32-bit mask scan | O(32) = O(1) | O(1) |
MSB via Math.clz32 | O(1) | O(1) |
log is base 2 in the bit-length sense for nonnegative n.
Summary
- Idea: collect
n % 2while halvingn; print in reverse, or scan bits MSB-down. - Code: handle
0; prefern >>> 0for a 32-bit unsigned bit pattern. - Pair: binary-to-decimal for the reverse direction.
Repeated division by 2 collects bits from least to most significant, so the usual classroom program prints the array backwards. A bit-mask loop prints from the MSB without an explicit reversal.
8 people found this page helpful
