Powers of Eight
Base 8
Each digit is a coefficient on 1, 8, 64, 512…
Decimal-to-octal conversion turns a base-10 integer into a base-8 digit string (digits 0–7). This tutorial covers remainders, recursion, built-ins, a live preview, worked JavaScript examples, edge cases, and complexity.
Base 8
Each digit is a coefficient on 1, 8, 64, 512…
n % 8
Collect digits LSD-first, then reverse for MSD-first output.
MSB first
Recurse on Math.floor(n / 8) before appending n % 8 — no reverse array.
Special case
Return "0" — a plain while n > 0 loop would print nothing.
3 bits each
One octal digit equals exactly three binary bits.
Complexity
About log8 n digits for nonnegative n.
Decimal-to-octal conversion writes a nonnegative integer using digits 0–7 only. Classic example: 57 = 7 × 8 + 1 → octal 71.
The classroom method divides by 8 and stacks remainders (LSD first), then reverses. Recursion or n.toString(8) can produce the same string more directly.
It generalizes the binary conversion pattern, trains base-8 place value, and links neatly to binary triplets.
First remainder is the rightmost digit.
MSD-first output needs a reverse (or recursion).
Always return "0" for input 0.
Each octal digit packs three bits.
In short: repeatedly take n % 8 and Math.floor(n / 8), reverse the digits (or recurse MSD-first), and special-case zero.
Given a nonnegative integer n, return its octal representation as a string (minimal digits, no leading zeros except for 0).
// 57 → remainders 1, 7 → reverse → "71"
// 64 → "100"
// 0 → "0" | Item | Type | Description |
|---|---|---|
n | number | Nonnegative integer (define policy for negatives). |
| Return / print | string | Octal digits as a string, e.g. "71". |
function decimalToOctal(n) { // n >= 0
if (n === 0) return "0";
const digits = [];
while (n > 0) {
digits.push(String(n % 8));
n = Math.floor(n / 8);
}
return digits.reverse().join("");
} | Method | Idea | Notes |
|---|---|---|
| Remainder + reverse | Collect n % 8, then reverse | Best classroom / interview explanation |
| Recursive MSD-first | Recurse on Math.floor(n / 8), then append n % 8 | No reverse list |
| Built-in | n.toString(8) | Idiomatic production JavaScript |
| Goal | Pattern |
|---|---|
| Next digit | n % 8 |
| Drop digit | n = Math.floor(n / 8) |
| MSD-first output | digits.reverse() or recurse first |
| Zero case | if (n === 0) return "0" |
| Built-in | n.toString(8) |
| Binary grouping | 3 bits ↔ 1 octal digit |
Same octal string — different clarity and interview signaling.
% 8 + reverseShows place-value / division clearly
MSD firstCall stack delays lower digits naturally
toString(8)Shortest production style
remainders firstExplain loops, then mention built-ins
Reach for decimal-to-octal drills when base-8 conversion and binary grouping matter.
Same remainder pattern as binary, with digits 0–7.
Octal is a compact way to read binary in groups of three.
Classic chmod modes are often written in octal.
Same idea with base 16 and digit alphabet 0–9A–F.
Fractional octal needs a different place-value story after the point.
Key benefit: one short problem that generalizes binary conversion and connects neatly to 3-bit grouping.
Nonnegative integers in JavaScript safe range, using toString(8).
Three complete JavaScript programs with Try it Yourself editors — remainder + reverse, recursive MSD-first, and built-in formatting. Click View Output to reveal sample console results.
Classic divide-by-eight approach — collect, then reverse.
Collect remainder digits LSD-first, then reverse to print MSD-first.
function decimalToOctal(n) {
if (n === 0) {
return "0";
}
const digits = [];
while (n > 0) {
digits.push(String(n % 8));
n = Math.floor(n / 8);
}
return digits.reverse().join("");
}
console.log("Octal equivalent:", decimalToOctal(57));
console.log("Octal equivalent:", decimalToOctal(0)); Remainders come from right to left, so reversing is required for proper left-to-right octal display.
No explicit reversal list — the call stack prints higher digits first.
Recurse on Math.floor(n / 8), then append n % 8.
function printOctalRecursive(n) {
if (n < 8) {
return String(n);
}
return printOctalRecursive(Math.floor(n / 8)) + String(n % 8);
}
console.log("57 in octal:", printOctalRecursive(57));
console.log("0 in octal:", printOctalRecursive(0)); The call stack naturally delays lower digits until higher digits are printed — base case n < 8 returns a single digit (including 0).
Same answer with built-ins — great after you know the algorithm.
toString(8)Minimal digits, plus a quick binary-triplet check.
function toOctalBuiltin(n) {
if (n < 0) {
throw new Error("This helper expects a nonnegative integer");
}
return n.toString(8);
}
console.log(toOctalBuiltin(57));
console.log(toOctalBuiltin(0));
console.log((57).toString(8)); // same as above
console.log((57).toString(2)); // binary of 57
// 71 octal ↔ 111 001 binary (7=111, 1=001) n.toString(8) is the cleanest minimal-digit conversion. Grouping binary 111001 as 111 001 recovers octal digits 7 and 1.
If n === 0, return "0" immediately.
Append n % 8, then set n = Math.floor(n / 8) until n becomes 0.
Reverse the list (or have recursed MSD-first) and join into a string.
Return the MSD-first digit string — that is the base-8 form of n.
n = 57Trace the remainder method. Digits collect LSD-first, then reverse.
| n | n % 8 | Math.floor(n / 8) | digits so far |
|---|---|---|---|
57 | 1 | 7 | [1] |
7 | 7 | 0 | [1, 7] |
Reverse → 71. Check: 7 × 8 + 1 = 57.
Where decimal-to-octal conversion shows up beyond the interview prompt.
Generalizes binary conversion to another base.
Example: write decimalToOctal(n).
Map each octal digit to three bits.
Example: 7 ↔ 111.
Unix modes are often written in octal.
Example: 755, 644.
Same remainder idea with base 16.
Example: n % 16 + digit map.
Convert to octal then back with parseInt(s, 8).
Example: assert parseInt(octal, 8) === n.
MSD-first print is a clean recursion demo.
Example: recurse then append remainder.
Pro Tip: say “first remainder is the LSD” before coding — same tip as for binary, with base 8.
Why this pattern works well in interviews and classwork.
Same structure as decimal-to-binary — only the divisor changes.
Three-bit groups make mental conversion fast.
n.toString(8) keeps application code short after the theory.
O(log8 n) digits are easy to argue in interviews.
Pro Tip: after binary, ask yourself “what changes for octal?” — answer: divisor 8 and digit range 0–7.
Small habits that keep decimal-to-octal solutions interview-ready.
Return "0" before the remainder loop.
Then reverse (or recurse) for MSD-first print.
Expect 71 and 10 as golden tests.
Shows you understand why octal exists historically.
Show the loop first; then n.toString(8).
Pro Tip: round-trip with parseInt(octal, 8) to catch reverse mistakes instantly.
Mistakes that commonly break decimal-to-octal solutions.
Printing remainders in collection order reverses the digits.
→ Reverse the list (or recurse MSD-first).
while n > 0 never runs when n is 0.
→ Return "0" explicitly.
Copying a decimal digit-extraction loop is a common slip.
→ Use % 8 and Math.floor(n / 8).
Some languages prefix octal with 0o; JavaScript uses 0o only in numeric literals, not in toString(8) output.
→ Use n.toString(8) for digit-only strings.
Very large integers can hit recursion limits.
→ Prefer the iterative remainder method for huge values.
Set rules for negative numbers early; many beginner versions accept only nonnegative input.
n == 0Without explicit handling, loop-based code can return empty output.
Either reject negatives or define representation convention clearly.
Octal never uses digits 8 or 9.
Become 10, 100, 1000 — good reverse checks.
Already octal — return unchanged as a string.
For extremely large integers, iterative methods avoid recursion depth concerns.
Handy follow-ups interviewers sometimes ask.
parseInt(s, 8).floor(log8 n) + 1 octal digits.Try these variations to lock in the pattern.
parseInt(s, 8)% 8 and divide by 8.Quick Takeaway: collect n % 8 remainders, reverse them (or recurse MSD-first), and special-case zero.
| Approach | Time | Extra space |
|---|---|---|
| Remainder + reverse list | O(log8 n) | O(log8 n) |
| Recursive print | O(log8 n) | O(log8 n) stack |
| Built-in toString(8) | Typically O(d) digits | O(d) output |
Here n is nonnegative and d is the number of octal digits.
Decimal-to-octal conversion is the binary remainder pattern with divisor 8: collect digits LSD-first, reverse for MSD-first output, and handle zero. Recursion and toString(8) are strong follow-ups once the theory is clear.
Practice the three examples above, then continue to Disarium numbers for a digit-power warm-up.
Always special-case 0, remember the first remainder is the LSD, and mention the 3-bit binary link.
Convert base 10 the interview-friendly way.
Remainders are digits
DefinitionDivide by 8
MathReturn "0"
Guard3 bits each
LinkO(log n)
AnalysisEach 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.
Learn how to check whether a number equals the sum of its digits raised to their positional powers.
9 people found this page helpful