Created
September 7, 2018 12:55
-
-
Save kopiro/27a3a2432debbb85651912c53d6e746b to your computer and use it in GitHub Desktop.
Number to English
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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