Developer

Binary Converter

Convert between binary, decimal, hex, and octal — live. Visualize bits and convert ASCII text.

Decimal base 10
42
Binary base 2
101010
Hexadecimal base 16
2A
Octal base 8
52
Bit Visualization (32-bit)

ASCII Text ↔ Binary
Binary will appear here
Text will appear here
Developer Reference

Core Algorithm & Standalone Script

Standalone, zero-dependency JavaScript implementation powering this tool. Free to inspect, copy, and build upon.

let currentBase = 10;
  const PATTERNS = { 10: /^-?\d+$/, 2: /^[01]+$/, 16: /^[0-9a-fA-F]+$/, 8: /^[0-7]+$/ };
  const LABELS = { 10: 'Decimal value', 2: 'Binary value (0s and 1s)', 16: 'Hexadecimal value (0–9, A–F)', 8: 'Octal value (0–7)' };
  const PLACEHOLDERS = { 10: '42', 2: '101010', 16: '2A', 8: '52' };

  const mainInput = document.getElementById('mainInput');
  const errorHint = document.getElementById('errorHint');

  // Base toggle
  document.getElementById('baseToggle').addEventListener('click', e => {
    const btn = e.target.closest('.base-btn');
    if (!btn) return;
    document.querySelectorAll('.base-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    currentBase = parseInt(btn.dataset.base);
    document.getElementById('inputLabel').textContent = LABELS[currentBase];
    mainInput.placeholder = PLACEHOLDERS[currentBase];

    // Highlight active card
    [10, 2, 16, 8].forEach(b => {
      document.getElementById(`card-${b}`).classList.toggle('active-base', b === currentBase);
    });

    // Convert current displayed value into new base
    const decVal = getCurrentDecimal();
    if (decVal !== null) {
      mainInput.value = decVal.toString(currentBase).toUpperCase();
    }

    errorHint.textContent = '';
    mainInput.classList.remove('input-error');
    convert();
  });

  mainInput.addEventListener('input', convert);

  function getCurrentDecimal() {
    // Get the decimal value from the conversion display
    const decText = document.getElementById('val-dec').textContent;
    const n = parseInt(decText, 10);
    return isNaN(n) ? null : n;
  }

  function convert() {
    const raw = mainInput.value.trim();
    if (!raw) {
      clearOutputs();
      return;
    }

    const pattern = PATTERNS[currentBase];
    const isNeg = currentBase === 10 && raw.startsWith('-');
    const testVal = isNeg ? raw.slice(1) : raw;

    if (!pattern.test(raw)) {
      errorHint.textContent = `Invalid input for base ${currentBase}`;
      mainInput.classList.add('input-error');
      clearOutputs();
      return;
    }

    errorHint.textContent = '';
    mainInput.classList.remove('input-error');

    let decimal;
    try {
      decimal = parseInt(raw, currentBase);
      if (isNaN(decimal)) throw new Error();
    } catch {
      clearOutputs();
      return;
    }

    // Render all
    const bin = decimal < 0 ? '-' + Math.abs(decimal).toString(2) : decimal.toString(2);
    document.getElementById('val-dec').textContent = decimal.toString(10);
    document.getElementById('val-dec').classList.remove('muted');
    document.getElementById('val-bin').textContent = bin;
    document.getElementById('val-bin').classList.remove('muted');
    document.getElementById('val-hex').textContent = decimal < 0
      ? '-' + Math.abs(decimal).toString(16).toUpperCase()
      : decimal.toString(16).toUpperCase();
    document.getElementById('val-hex').classList.remove('muted');
    document.getElementById('val-oct').textContent = decimal < 0
      ? '-' + Math.abs(decimal).toString(8)
      : decimal.toString(8);
    document.getElementById('val-oct').classList.remove('muted');

    // Bit visualization (32-bit, only for non-negative ≤ 2^32-1)
    renderBits(decimal);
  }

  function clearOutputs() {
    ['val-dec','val-bin','val-hex','val-oct'].forEach(id => {
      document.getElementById(id).textContent = '—';
      document.getElementById(id).classList.add('muted');
    });
    document.getElementById('bitGrid').innerHTML = '';
  }

  function renderBits(decimal) {
    const bitGrid = document.getElementById('bitGrid');
    if (decimal < 0 || decimal > 0xFFFFFFFF) {
      bitGrid.innerHTML = '<div style="color:var(--muted);font-size:12px;">Bit visualization available for 0 – 4,294,967,295</div>';
      return;
    }

    const bits = decimal.toString(2).padStart(32, '0').split('');
    bitGrid.innerHTML = '';

    // 4 rows of 8 bits
    for (let row = 0; row < 4; row++) {
      const rowBits = bits.slice(row * 8, row * 8 + 8);
      const bitNum = 31 - row * 8; // most significant bit in row
      const div = document.createElement('div');
      div.className = 'bit-row';
      div.innerHTML = `<span class="bit-row-label">bit ${bitNum}–${bitNum - 7}</span>` +
        rowBits.map((b, i) => {
          const bitIndex = 31 - (row * 8 + i);
          return `<div class="bit ${b === '1' ? 'one' : 'zero'}" title="bit ${bitIndex}">${b}</div>`;
        }).join('');
      bitGrid.appendChild(div);
    }
  }

  // Copy helpers
  const vals = { dec: 'val-dec', bin: 'val-bin', hex: 'val-hex', oct: 'val-oct' };
  function copyCard(key) {
    const text = document.getElementById(vals[key]).textContent;
    if (text === '—') return;
    const btn = event.target;
    navigator.clipboard.writeText(text).then(() => {
      btn.textContent = 'copied!';
      setTimeout(() => btn.textContent = 'copy', 2000);
    });
  }

  function copyOutput(parentId) {
    const parent = document.getElementById(parentId);
    const textEl = parent.querySelector('span');
    if (!textEl) return;
    const btn = parent.querySelector('.copy-btn');
    navigator.clipboard.writeText(textEl.textContent).then(() => {
      btn.textContent = 'copied!';
      setTimeout(() => btn.textContent = 'copy', 2000);
    });
  }

  // ASCII ↔ Binary
  document.getElementById('asciiInput').addEventListener('input', e => {
    const text = e.target.value;
    const outEl = document.getElementById('asciiOutputText');
    if (!text) {
      outEl.textContent = 'Binary will appear here';
      outEl.style.fontStyle = 'italic';
      outEl.style.color = 'var(--muted)';
      return;
    }
    const binary = text.split('').map(c => c.charCodeAt(0).toString(2).padStart(8, '0')).join(' ');
    outEl.textContent = binary;
    outEl.style.fontStyle = 'normal';
    outEl.style.color = 'var(--text)';
  });

  document.getElementById('binInput').addEventListener('input', e => {
    const raw = e.target.value.trim();
    const outEl = document.getElementById('binOutputText');
    if (!raw) {
      outEl.textContent = 'Text will appear here';
      outEl.style.fontStyle = 'italic';
      outEl.style.color = 'var(--muted)';
      return;
    }
    const bytes = raw.split(/\s+/);
    const invalid = bytes.some(b => !/^[01]{1,8}$/.test(b));
    if (invalid) {
      outEl.textContent = 'Invalid binary — use 8-bit bytes separated by spaces';
      outEl.style.color = 'var(--error)';
      outEl.style.fontStyle = 'italic';
      return;
    }
    try {
      const text = bytes.map(b => String.fromCharCode(parseInt(b, 2))).join('');
      outEl.textContent = text;
      outEl.style.fontStyle = 'normal';
      outEl.style.color = 'var(--text)';
    } catch {
      outEl.textContent = 'Conversion error';
      outEl.style.color = 'var(--error)';
    }
  });

  // Init
  [10, 2, 16, 8].forEach(b => {
    document.getElementById(`card-${b}`).classList.toggle('active-base', b === currentBase);
  });
  convert();