Convert Decimal to Octal in JavaScript

Beginner
⏱️ 9 min read
📚 Updated: May 2026
🎯 2 Code examples + Try it
Base conversion

What you’ll learn

  • How division by eight and remainders produce octal digits 07.
  • 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, and n >>> 0 for a 32-bit unsigned view like C’s unsigned int.
  • ES2015 octal literals 0o71 vs legacy 057 (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 1718.

Decimal base 10
Octal base 8
Digits 0 – 7

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.

57

57 = 8·7 + 1, then 7 = 8·0 + 7. Remainders LSB-first: 1, 7 → octal 71.

Intuition

64 100 (oct)
Power
82
57 71 (oct)
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).

Negative values are rejected; signed formatting is a separate policy.

Live result
Press “Show octal” to convert.

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

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 order
1

Divide 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).

JavaScript
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);
Try it Yourself

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.

2

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.

JavaScript
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));
Try it Yourself

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 AF 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

Octal is base 8. The remainder n % 8 is the least significant octal digit; integer division n/8 removes that digit, just like decimal to binary uses 2.
The first remainder is the rightmost (least significant) octal digit. Printing from last remainder to first yields MSB-to-LSB order.
while (n !== 0) never runs, so you must print 0 explicitly; otherwise you only print the label and a blank line.
Yes: n.toString(8) (or Number(n).toString(8)) prints a minimal unsigned octal string for nonnegative n in JavaScript. It is a good shortcut after you understand the manual algorithm.
One octal digit encodes exactly three bits. Converting binary to octal groups bits in threes from the radix point outward.
O(log8 n) = O(log n) octal digits for nonnegative n using the remainder method; the recursive string build does one call per digit.

🔄 Input / output examples

Example 1 uses 57 and 0; Example 2 repeats 57 and 0 with the recursive string builder.

DecimalOctal
00
77
810
5771
64100

Edge cases and pitfalls

Signed negatives with truncating division do not give a clean “unsigned octal string” without an explicit policy.

Zero

n == 0

The reference while (decimalNumber !== 0) skips the loop; always print 0 explicitly.

Digits

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.

Recursion

Very wide integers

For arbitrary-precision n, prefer an iterative loop or an explicit stack to avoid deep recursion.

Prefix

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

ApproachTimeExtra space
Remainder + arrayO(log8 n) digitsO(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, divide n by 8, reverse for display.
  • Code: guard 0; use n >>> 0 for clean 32-bit nonnegative semantics.
  • Extra: octal lines up with binary in groups of three bits.
Did you know?

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.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful