Skip to content

Instantly share code, notes, and snippets.

@kopiro
Created September 7, 2018 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kopiro/27a3a2432debbb85651912c53d6e746b to your computer and use it in GitHub Desktop.
Save kopiro/27a3a2432debbb85651912c53d6e746b to your computer and use it in GitHub Desktop.
Number to English
const digit_to_string = {
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: 'forty',
50: 'fifty',
60: 'sixty',
70: 'seventy',
80: 'eighty',
90: 'ninety',
100: 'hundred',
1000: 'thousand',
1000000: 'million',
1000000000: 'billion',
1000000000000: 'trillion',
1000000000000000: 'quadrillion'
};
const recursive_processed_numbers = [
1000000000000000,
1000000000000,
1000000000,
1000000,
1000,
100,
];
function stringExtractor(n, strings = []) {
// If the value is 0, there's nothing more to process
if (n === 0) return strings;
// If we arrived here froma recursive call, we have to add the separators
if (strings.length) {
let conj = ' ';
if (strings[strings.length-1] === digit_to_string[100]) conj = ' and ';
if (n < 100) conj = ' and ';
strings.push(conj);
}
// Iterate over the numbers that we have to treat as recursive
for (let g of recursive_processed_numbers) {
// Only if the number is greater than one of these numbers
if (n >= g) {
// Extract the left part
let pre_n = ~~(n/g);
// Parse that numbers as strings
let pre_strings = stringExtractor(pre_n);
// And push into the strings with a space separator and his word representation
strings = strings.concat(
pre_strings,
' ',
digit_to_string[g]
);
// And now process the remaining (n - (pre_n*g)) right part
return stringExtractor(n - (pre_n*g), strings);
}
}
// Store previous N value in the while
let prev = null;
// Process while there's something to process
while (n > 0) {
// Find the greatest digit < N
let my_digit = null;
for (let d in digit_to_string) {
if (d <= n) my_digit = d;
else break;
}
// This should be never reached
if (my_digit == null) throw new Error();
// If the previous value is 20 >= n <= 90, add an '-'
if (prev >= 20 && prev <= 90) strings.push('-');
// Push this value into the strings
strings.push(digit_to_string[my_digit]);
// Store previous value
prev = my_digit|0;
// And subtract current found digit from N
n -= my_digit|0;
}
return strings;
}
function numberToEnglish(n) {
// Edge cases
if (isNaN(n)) throw new Error();
if (n === 0) return 'zero';
if (n === Infinity) return 'infinity';
if (n === -Infinity) return 'negative infinity';
// If it's a comma, extract the decimal part
let n_int, n_dec;
let n_dec_index = String(n).indexOf('.');
if (n_dec_index !== -1) {
n_int = Math.abs(parseFloat(String(n).substr(0, n_dec_index)));
n_dec = String(n).substr(1+n_dec_index);
} else {
n_int = Math.abs(n);
n_dec = null;
}
// Process the integer part
let result = stringExtractor(n_int);
// If is a zero length result, it's because it's a zero
if (result.length === 0) result = [digit_to_string[0]];
// Glue pieces together
result = result.join('');
// Process the decimal part
if (n_dec != null) {
result = result + ' point ' + n_dec.split('').map(digit => digit_to_string[digit]).join(' ');
}
// Return
return (n < 0 ? 'negative ' : '') + result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment