UNPKG

@mahmud002/number-to-words-converter

Version:

A simple utility to convert numbers to their word representations in English and Persian, and vice versa. Includes Persian numerals conversion.

419 lines (418 loc) 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.numberToWords = numberToWords; exports.numberToPersianWords = numberToPersianWords; exports.wordsToNumber = wordsToNumber; exports.persianWordsToNumber = persianWordsToNumber; exports.stringToNumber = stringToNumber; exports.numberToString = numberToString; exports.numberToPersianNumerals = numberToPersianNumerals; exports.persianNumeralsToNumber = persianNumeralsToNumber; 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']; const SCALES = ['', 'thousand', 'million', 'billion', 'trillion']; // Persian number arrays const PERSIAN_ONES = [ '', 'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه', 'ده', 'یازده', 'دوازده', 'سیزده', 'چهارده', 'پانزده', 'شانزده', 'هفده', 'هجده', 'نوزده', ]; const PERSIAN_TENS = ['', '', 'بیست', 'سی', 'چهل', 'پنجاه', 'شصت', 'هفتاد', 'هشتاد', 'نود']; const PERSIAN_HUNDREDS = [ '', 'صد', 'دویست', 'سیصد', 'چهارصد', 'پانصد', 'ششصد', 'هفتصد', 'هشتصد', 'نهصد', ]; const PERSIAN_SCALES = ['', 'هزار', 'میلیون', 'میلیارد', 'تریلیون']; // Persian numerals mapping const PERSIAN_NUMERALS = { '۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4', '۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9', }; // Persian numerals mapping (reverse) const ENGLISH_TO_PERSIAN_NUMERALS = { '0': '۰', '1': '۱', '2': '۲', '3': '۳', '4': '۴', '5': '۵', '6': '۶', '7': '۷', '8': '۸', '9': '۹', }; // English number words to numeric mapping const ENGLISH_WORD_TO_NUMBER = { zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9, ten: 10, eleven: 11, twelve: 12, thirteen: 13, fourteen: 14, fifteen: 15, sixteen: 16, seventeen: 17, eighteen: 18, nineteen: 19, twenty: 20, thirty: 30, forty: 40, fifty: 50, sixty: 60, seventy: 70, eighty: 80, ninety: 90, hundred: 100, thousand: 1000, million: 1000000, billion: 1000000000, trillion: 1000000000000, }; // Persian number words to numeric mapping const PERSIAN_WORD_TO_NUMBER = { صفر: 0, یک: 1, دو: 2, سه: 3, چهار: 4, پنج: 5, شش: 6, هفت: 7, هشت: 8, نه: 9, ده: 10, یازده: 11, دوازده: 12, سیزده: 13, چهارده: 14, پانزده: 15, شانزده: 16, هفده: 17, هجده: 18, نوزده: 19, بیست: 20, سی: 30, چهل: 40, پنجاه: 50, شصت: 60, هفتاد: 70, هشتاد: 80, نود: 90, صد: 100, دویست: 200, سیصد: 300, چهارصد: 400, پانصد: 500, ششصد: 600, هفتصد: 700, هشتصد: 800, نهصد: 900, هزار: 1000, میلیون: 1000000, میلیارد: 1000000000, تریلیون: 1000000000000, }; // English numerals to string mapping const ENGLISH_NUMERALS = { '0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five', '6': 'six', '7': 'seven', '8': 'eight', '9': 'nine', }; function convertChunk(num) { if (num === 0) return ''; let words = ''; // Handle hundreds if (num >= 100) { words += ONES[Math.floor(num / 100)] + ' hundred '; num %= 100; } // Handle tens and ones if (num > 0) { if (words !== '') { words += 'and '; } if (num < 20) { words += ONES[num]; } else { words += TENS[Math.floor(num / 10)]; if (num % 10 > 0) { words += '-' + ONES[num % 10]; } } } return words.trim(); } function convertPersianChunk(num) { if (num === 0) return ''; let words = ''; // Handle hundreds if (num >= 100) { words += PERSIAN_HUNDREDS[Math.floor(num / 100)] + ' '; num %= 100; } // Handle tens and ones if (num > 0) { if (words !== '') { words += 'و '; } if (num < 20) { words += PERSIAN_ONES[num]; } else { words += PERSIAN_TENS[Math.floor(num / 10)]; if (num % 10 > 0) { words += ' و ' + PERSIAN_ONES[num % 10]; } } } return words.trim(); } function numberToWords(num) { if (num === 0) return 'zero'; if (num < 0) return 'negative ' + numberToWords(Math.abs(num)); let words = ''; let scaleIndex = 0; while (num > 0) { const chunk = num % 1000; if (chunk > 0) { const chunkWords = convertChunk(chunk); words = chunkWords + (SCALES[scaleIndex] ? ' ' + SCALES[scaleIndex] + ' ' : '') + words; } num = Math.floor(num / 1000); scaleIndex++; } return words.trim().toLowerCase(); } function numberToPersianWords(input) { // Convert Persian numerals to English numerals if string input let num; if (typeof input === 'string') { num = parseInt(input .split('') .map((char) => PERSIAN_NUMERALS[char] || char) .join('')); } else { num = input; } if (isNaN(num)) { throw new Error('Invalid number input'); } if (num === 0) return 'صفر'; if (num < 0) return 'منفی ' + numberToPersianWords(Math.abs(num)); let words = ''; let scaleIndex = 0; let hasValue = false; while (num > 0) { const chunk = num % 1000; if (chunk > 0) { const chunkWords = convertPersianChunk(chunk); if (hasValue) { words = chunkWords + ' ' + PERSIAN_SCALES[scaleIndex] + ' و ' + words; } else { words = chunkWords + (PERSIAN_SCALES[scaleIndex] ? ' ' + PERSIAN_SCALES[scaleIndex] : '') + words; hasValue = true; } } num = Math.floor(num / 1000); scaleIndex++; } return words.trim(); } function wordsToNumber(words) { // Remove extra spaces and convert to lowercase words = words.toLowerCase().trim().replace(/\s+/g, ' '); // Handle negative numbers if (words.startsWith('negative ')) { return -wordsToNumber(words.slice(9)); } let total = 0; let currentNumber = 0; // Split into words and process each const wordArray = words.split(/[\s-]+/); for (let i = 0; i < wordArray.length; i++) { const word = wordArray[i]; if (word === 'and') continue; const value = ENGLISH_WORD_TO_NUMBER[word]; if (value === undefined) { throw new Error(`Unknown word: ${word}`); } if (value === 100) { currentNumber = (currentNumber || 1) * value; } else if (value >= 1000) { currentNumber = (currentNumber || 1) * value; total += currentNumber; currentNumber = 0; } else { currentNumber += value; } } return total + currentNumber; } function persianWordsToNumber(words) { // Handle negative numbers if (words.startsWith('منفی ')) { return -persianWordsToNumber(words.slice(5)); } let total = 0; let currentNumber = 0; // Split into words and process each const wordArray = words.split(/\s+و\s+|\s+/); for (let i = 0; i < wordArray.length; i++) { const word = wordArray[i].trim(); const value = PERSIAN_WORD_TO_NUMBER[word]; if (value === undefined) { throw new Error(`Unknown word: ${word}`); } if (value >= 1000) { currentNumber = (currentNumber || 1) * value; total += currentNumber; currentNumber = 0; } else { currentNumber += value; } } return total + currentNumber; } function stringToNumber(input) { // Try parsing as a regular number first const num = Number(input); if (!isNaN(num)) { return num; } // Convert Persian numerals to English numerals const englishNumerals = input .split('') .map((char) => PERSIAN_NUMERALS[char] || char) .join(''); const numFromPersian = Number(englishNumerals); if (!isNaN(numFromPersian)) { return numFromPersian; } // Try parsing as English words try { return wordsToNumber(input); } catch (e) { // Try parsing as Persian words try { return persianWordsToNumber(input); } catch (e2) { throw new Error('Invalid number format'); } } } function numberToString(num, format = 'english') { if (format === 'persian') { return numberToPersianWords(num); } return numberToWords(num); } function numberToPersianNumerals(num) { return num .toString() .split('') .map((digit) => ENGLISH_TO_PERSIAN_NUMERALS[digit] || digit) .join(''); } function persianNumeralsToNumber(persianNumerals) { const englishNumerals = persianNumerals .split('') .map((char) => PERSIAN_NUMERALS[char] || char) .join(''); return parseInt(englishNumerals); } exports.default = { numberToWords, numberToPersianWords, wordsToNumber, persianWordsToNumber, stringToNumber, numberToString, numberToPersianNumerals, persianNumeralsToNumber, };