- Power
82
Convert Decimal to Octal in JavaScript
What you’ll learn
- How division by eight and remainders produce octal digits
0–7. - Why zero needs a branch and why digits are printed in reverse of collection order.
- A recursive MSB-first string build without an array, a live preview, and ties to binary grouping.
Overview
Octal is base eight. To print a nonnegative decimal integer in octal, repeatedly take n % 8, then replace n by Math.floor(n / 8), until n is zero; emit the remainders from last to first.
Two programs
Array + reverse print (classic), then recursion for MSB-first output as a string.
Live preview
Nonnegative safe integers via Number#toString(8).
Pair with binary
Same remainder pattern as decimal-to-binary, divisor 8 instead of 2.
Prerequisites
Integer division and modulo, arrays, for and while loops, optional recursion.
console.log,Number.isSafeInteger, andn >>> 0for a 32-bit unsigned view like C’sunsigned int.- ES2015 octal literals
0o71vs legacy057(avoid confusing source notation with string output).
Decimal to octal
Each octal digit is a coefficient on a power of eight: dk8k + … + d080 with every di ∈ {0,…,7}. The peel operation n % 8 reads the least significant octal digit.
Reference value 57: 57 = 7·8 + 1, so octal digits (MSB to LSB) are 7 then 1 → 718.
Division algorithm
For n ≥ 0, let d0 = n mod 8 and n1 = ⌊n/8⌋, then repeat. The sequence of remainders read from last generated to first is the standard octal numeral for n.
5757 = 8·7 + 1, then 7 = 8·0 + 7. Remainders LSB-first: 1, 7 → octal 71.
Intuition
- Sum
7·8 + 1
Takeaway: each % 8 answers “which slice of eight fits in the current place?”
Live preview
Nonnegative integers in the JavaScript safe range. Uses Number#toString(8).
Algorithm (remainder method)
Goal: print octal digits of nonnegative n in MSB-first order.
Special case n == 0
Print 0 when n is zero; while (n !== 0) alone skips the body.
Collect digits
While n > 0: push n % 8, then n = Math.floor(n / 8).
Print reversed
Emit stored digits from last pushed to first.
📜 Pseudocode
function printOctalFromDecimal(n): // n ≥ 0
if n = 0:
output "0"; return
digits ← empty list
while n > 0:
append (n mod 8) to digits
n ← floor(n / 8)
print digits in reverse orderDivide by eight with reverse print
Matches the reference flow with a zero branch and n >>> 0 for unsigned 32-bit semantics. Uses a small digit buffer (more than enough for typical magnitudes).
function decimalToOctal(decimalNumber) {
const octalDigits = [];
let n = decimalNumber >>> 0;
if (n === 0) {
console.log("Octal equivalent: 0");
return;
}
while (n !== 0) {
octalDigits.push(n % 8);
n = Math.floor(n / 8);
}
let line = "Octal equivalent: ";
for (let j = octalDigits.length - 1; j >= 0; j--) {
line += String(octalDigits[j]);
}
console.log(line);
}
const decimalNumber = 57 >>> 0;
decimalToOctal(decimalNumber);
decimalToOctal(0);Explanation
Each remainder is in 0..7 by construction, so a single decimal digit per position is enough for display (no letters until base 11).
while (n !== 0)Same stopping test as the reference, paired with an upfront 0 print.
Recursive MSB-first (no digit array)
Builds the string high-to-low: recurse on Math.floor(n/8) until n < 8, then append n % 8 on the way back—equivalent to the C putchar order, returned as one string for console.log.
function printOctalMsbRecursive(n) {
const u = n >>> 0;
if (u < 8) {
return String(u);
}
return printOctalMsbRecursive(Math.floor(u / 8)) + String(u % 8);
}
console.log("57 in octal: " + printOctalMsbRecursive(57));
console.log("0 in octal: " + printOctalMsbRecursive(0));Explanation
The recursion depth equals the number of octal digits; for 32-bit unsigned values that is at most 11.
String(u % 8)Decimal digit character. Octal never needs A–F like hexadecimal.
Optimization and library path
n.toString(8). For nonnegative n, returns minimal octal digits without loops once you accept built-in formatting rules.
From binary. Group bits in threes from the right to jump between bases without repeated division by eight.
Interview: state nonnegative assumption, n==0, and the 3-bit grouping trick.
❓ FAQ
🔄 Input / output examples
Example 1 uses 57 and 0; Example 2 repeats 57 and 0 with the recursive string builder.
| Decimal | Octal |
|---|---|
0 | 0 |
7 | 7 |
8 | 10 |
57 | 71 |
64 | 100 |
Edge cases and pitfalls
Signed negatives with truncating division do not give a clean “unsigned octal string” without an explicit policy.
n == 0
The reference while (decimalNumber !== 0) skips the loop; always print 0 explicitly.
Remainder range
For nonnegative n, n % 8 is always in 0..7. If you ever see 8 or 9, the type or sign handling is wrong.
Very wide integers
For arbitrary-precision n, prefer an iterative loop or an explicit stack to avoid deep recursion.
Leading 0 in source code
In legacy JavaScript, a leading 0 could denote octal in sloppy modes; use explicit 0o literals in modern code. Do not confuse literal syntax with string output.
⏱️ Time and space complexity
| Approach | Time | Extra space |
|---|---|---|
| Remainder + array | O(log8 n) digits | O(log8 n) stored digits |
| Recursion (Example 2) | O(log8 n) | O(log8 n) call frames |
toString(8) | Engine-defined; typically O(d) | O(1) extra beyond the output string |
Here n is the magnitude of a nonnegative input.
Summary
- Idea: collect
n % 8, dividenby8, reverse for display. - Code: guard
0; usen >>> 0for clean 32-bit nonnegative semantics. - Extra: octal lines up with binary in groups of three bits.
Each octal digit corresponds to a block of three binary bits, which is why Unix file modes and some literals are still written in base eight.
8 people found this page helpful
