@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
JavaScript
;
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,
};