Text

NUMBER TO WORDS

Convert any number to English words. Choose International (millions/billions) or Indian (lakhs/crores) system. Supports decimals, negatives, and ordinals.

Words
Enter a number above
Developer Reference

Core Algorithm & Standalone Script

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

let system = 'intl';
  let showOrdinal = false;

  const ones = ['','one','two','three','four','five','six','seven','eight','nine',
    'ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'];
  const tens = ['','','twenty','thirty','forty','fifty','sixty','seventy','eighty','ninety'];

  function threeDigits(n) {
    if (n === 0) return '';
    if (n < 20) return ones[n];
    if (n < 100) return tens[Math.floor(n/10)] + (n%10 ? ' ' + ones[n%10] : '');
    return ones[Math.floor(n/100)] + ' hundred' + (n%100 ? ' ' + threeDigits(n%100) : '');
  }

  function toWordsIntl(n) {
    if (n === 0) return 'zero';
    let result = '';
    if (n < 0) { result = 'negative '; n = -n; }
    const groups = [
      [1e12, 'trillion'], [1e9, 'billion'], [1e6, 'million'], [1e3, 'thousand']
    ];
    for (const [val, name] of groups) {
      if (n >= val) {
        result += toWordsIntl(Math.floor(n / val)) + ' ' + name + ' ';
        n = n % val;
      }
    }
    if (n > 0) result += threeDigits(Math.floor(n));
    return result.trim();
  }

  function toWordsIndian(n) {
    if (n === 0) return 'zero';
    let result = '';
    if (n < 0) { result = 'negative '; n = -n; }
    if (n >= 1e7) {
      result += toWordsIndian(Math.floor(n / 1e7)) + ' crore ';
      n = n % 1e7;
    }
    if (n >= 1e5) {
      result += toWordsIndian(Math.floor(n / 1e5)) + ' lakh ';
      n = n % 1e5;
    }
    if (n >= 1e3) {
      result += toWordsIndian(Math.floor(n / 1e3)) + ' thousand ';
      n = n % 1e3;
    }
    if (n > 0) result += threeDigits(Math.floor(n));
    return result.trim();
  }

  const ordinalMap = {
    one:'first', two:'second', three:'third', four:'fourth', five:'fifth',
    six:'sixth', seven:'seventh', eight:'eighth', nine:'ninth', ten:'tenth',
    eleven:'eleventh', twelve:'twelfth', thirteen:'thirteenth', fourteen:'fourteenth',
    fifteen:'fifteenth', sixteen:'sixteenth', seventeen:'seventeenth', eighteen:'eighteenth',
    nineteen:'nineteenth', twenty:'twentieth', thirty:'thirtieth', forty:'fortieth',
    fifty:'fiftieth', sixty:'sixtieth', seventy:'seventieth', eighty:'eightieth', ninety:'ninetieth',
    hundred:'hundredth', thousand:'thousandth', million:'millionth', billion:'billionth',
    trillion:'trillionth', lakh:'lakhth', crore:'croreth',
  };

  function makeOrdinal(words) {
    if (!words || words === 'zero') return 'zeroth';
    const parts = words.split(' ');
    const last = parts[parts.length - 1];
    parts[parts.length - 1] = ordinalMap[last] || last + 'th';
    return parts.join(' ');
  }

  function convert() {
    const raw = document.getElementById('numInput').value.trim().replace(/,/g, '');
    const errEl = document.getElementById('errorMsg');
    const resWords = document.getElementById('resWords');
    const resOrdinal = document.getElementById('resOrdinal');

    if (!raw) {
      resWords.textContent = 'Enter a number above';
      resWords.classList.add('empty');
      errEl.style.display = 'none';
      return;
    }

    if (!/^-?\d+(\.\d+)?$/.test(raw)) {
      errEl.textContent = 'Please enter a valid number (digits only, optional decimal point).';
      errEl.style.display = 'block';
      resWords.textContent = '—';
      resWords.classList.add('empty');
      return;
    }
    errEl.style.display = 'none';

    const num = parseFloat(raw);
    if (!isFinite(num)) { errEl.textContent = 'Number is too large to process.'; errEl.style.display='block'; return; }

    const intPart = Math.floor(Math.abs(num));
    const decStr = raw.includes('.') ? raw.split('.')[1] : '';
    const negative = num < 0;

    let wordsFn = system === 'intl' ? toWordsIntl : toWordsIndian;
    let words = (negative ? 'negative ' : '') + wordsFn(intPart);

    if (decStr) {
      words += ' point ' + decStr.split('').map(d => ones[parseInt(d)] || 'zero').join(' ');
    }

    resWords.textContent = words.charAt(0).toUpperCase() + words.slice(1);
    resWords.classList.remove('empty');

    if (showOrdinal) {
      document.getElementById('ordinalBlock').style.display = '';
      const ordWords = makeOrdinal(wordsFn(intPart));
      resOrdinal.textContent = ordWords.charAt(0).toUpperCase() + ordWords.slice(1);
    }
  }

  function setSystem(s) {
    system = s;
    document.getElementById('btnIntl').classList.toggle('active', s === 'intl');
    document.getElementById('btnIndian').classList.toggle('active', s === 'indian');
    convert();
  }

  function toggleOrdinal() {
    showOrdinal = !showOrdinal;
    document.getElementById('btnOrdinal').classList.toggle('active', showOrdinal);
    document.getElementById('ordinalBlock').style.display = showOrdinal ? '' : 'none';
    convert();
  }

  function copyResult(id, btn) {
    const val = document.getElementById(id).textContent;
    if (!val || val === '—' || val === 'Enter a number above') return;
    navigator.clipboard.writeText(val).catch(() => {});
    btn.textContent = 'copied!'; btn.classList.add('copied');
    setTimeout(() => { btn.textContent = 'copy'; btn.classList.remove('copied'); }, 2000);
  }