Str/numberToWords.js

/**
 * Convert a number into words
 *
 * @memberof Str
 * @param {number} number
 * @return {string}
 */
function numberToWords(number) {
	const dictionary = {
		0: 'zero',
		1: 'one',
		2: 'two',
		3: 'three',
		4: 'four',
		5: 'five',
		6: 'six',
		7: 'seven',
		8: 'eight',
		9: 'nine',
		10: 'ten',
		11: 'eleven',
		12: 'twelve',
		13: 'thirteen',
		14: 'fourteen',
		15: 'fifteen',
		16: 'sixteen',
		17: 'seventeen',
		18: 'eighteen',
		19: 'nineteen',
		20: 'twenty',
		30: 'thirty',
		40: 'fourty',
		50: 'fifty',
		60: 'sixty',
		70: 'seventy',
		80: 'eighty',
		90: 'ninety',
		100: 'hundred',
		1000: 'thousand',
		1000000: 'million',
		1000000000: 'billion',
		1000000000000: 'trillion',
		1000000000000000: 'quadrillion',
		1000000000000000000: 'quintillion',
	};
	if (typeof number !== 'number') {
		return false;
	}
	if ((number >= 0 && number < 0) || number < 0 - Number.MAX_SAFE_INTEGER) {
		// overflow
		throw new Error('convert_number_to_words only accepts numbers between -' + Number.MAX_SAFE_INTEGER + ' and ' + Number.MAX_SAFE_INTEGER);
	}
	if (number < 0) {
		return 'negative ' + numberToWords(Math.abs(number));
	}
	let string = null;
	let fraction = null;
	if (number.toString().indexOf('.') !== -1) {
		const temp = number.toString().split('.');
		number = parseInt(temp[0], 10);
		fraction = parseInt(temp[1], 10);
	}
	switch (true) {
		case number < 21:
			string = dictionary[number];
			break;
		case number < 100: {
			const tens = (parseInt(number / 10, 10)) * 10;
			const units = number % 10;
			string = dictionary[tens];
			if (units) {
				string += '-' + dictionary[units];
			}
			break;
		}
		case number < 1000: {
			const hundreds = parseInt(number / 100, 10);
			const remainder = number % 100;
			string = dictionary[hundreds] + ' ' + dictionary[100];
			if (remainder) {
				string += ' and ' + numberToWords(remainder);
			}
			break;
		}
		default: {
			const baseUnit = 1000 ** Math.floor(Math.log(number) / Math.log(1000));
			const numBaseUnits = parseInt(number / baseUnit, 10);
			const remainder = number % baseUnit;
			string = numberToWords(numBaseUnits) + ' ' + dictionary[baseUnit];
			if (remainder) {
				string += remainder < 100 ? ' and ' : ', ';
				string += numberToWords(remainder);
			}
			break;
		}
	}
	if (fraction && typeof fraction === 'number') {
		string += ' point ';
		const words = [];
		fraction.toString().split('').forEach((num) => {
			words.push(dictionary[num]);
		});
		string += words.join(' ');
	}
	return string;
}

export default numberToWords;