Skip to content

Instantly share code, notes, and snippets.

@brookjordan
Last active March 16, 2023 11:58
Show Gist options
  • Save brookjordan/4a4de9fb4926c2420206cedfbac3c78a to your computer and use it in GitHub Desktop.
Save brookjordan/4a4de9fb4926c2420206cedfbac3c78a to your computer and use it in GitHub Desktop.
const units = [
'zero',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
] as const;
const tens = [
'',
'ten',
'twenty',
'thirty',
'fourty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety',
] as const;
const exponents = [
'',
'thousand',
'million',
'billion',
'trillion',
'quadrillion',
'quintillion',
'sextillion',
'septillion',
'octillion',
'nonillion',
'decillion',
'undecillion',
'duodecillion',
'tredecillion',
'quattuordecillion',
'quindecillion',
'sexdecillion',
'septendecillion',
'octodecillion',
'novemdecillion',
'vigintillion',
] as const;
type NumberGroup = [number, number, number] | [number, number] | number[];
function renderNumberGroup(
numberGroup: NumberGroup,
exponent: number,
exponentCount: number,
) {
const unit = numberGroup.at(-1);
const ten = numberGroup.at(-2) || 0;
const hundred = numberGroup.at(-3) || 0;
const unitAndTen = +`${ten}${unit}`;
return `${
hundred ? `${units[hundred]} hundred${unitAndTen ? ' and ' : ''}` : ''
}${
unitAndTen && unitAndTen < 20
? units[unitAndTen]
: `${ten ? `${tens[ten]} ` : ''}${
unit ? units[unit] : ten || exponentCount > 1 ? '' : units[0]
}`
}${exponent ? ` ${exponents[exponent]},` : ''}`;
}
function buildTextNumber(number: number | bigint | `${number}`) {
const numbers = String(number).split('');
const numberGroups: NumberGroup[] = [];
numbers.reverse();
numbers.forEach((number) => {
const lastGroup = numberGroups.at(-1);
if (!lastGroup || lastGroup.length === 3) {
numberGroups.push([+number]);
return;
}
lastGroup.push(+number);
});
numberGroups.forEach((group) => group.reverse());
const namedNumberParts = numberGroups.map(
(numberGroup, index, numberGroups) => {
return renderNumberGroup(numberGroup, index, numberGroups.length);
},
);
namedNumberParts.reverse();
return namedNumberParts.join(' ');
}
export default buildTextNumber;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment