const getUnits = number => ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][number] const getTens = (tens, units) => tens === 1 ? ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'][units] : ['', '', 'twenty ', 'thirty ', 'fourty ', 'fifty ', 'sixty ', 'seventy ', 'eighty ', 'ninety '][tens] + getUnits(units) const getLargeNumber = number => ['', 'thousand, ', 'm', 'b', 'tr', 'quadr', 'quint', 'sext', 'sept', 'oct', 'non'][number] const getVeryLargeNumber = index => { if (index < 10) return getLargeNumber(index) const mappedIndex = (index - 9) / 3 const prefix = ['', 'un', 'duo', 'tre', 'quattor', 'quin', 'sex', 'septen', 'octo', 'novem'][mappedIndex % 10] const suffix = ['dec', 'vigint', 'trigint', 'quadragint', 'quinquagint', 'sexagint', 'septuagint', 'octogint', 'nonagint'][~~(mappedIndex / 10)] return `${prefix}${suffix}` } const buildThreeDigits = (numeral, more) => { const tensNumber = getTens(~~((numeral % 100) / 10), (numeral % 100) % 10) const hundredsNumber = getUnits(~~(numeral / 100)) ? getUnits(~~(numeral / 100)) + ' hundred ' : '' const and = (hundredsNumber || more) && tensNumber ? 'and ' : '' return `${hundredsNumber}${and}${tensNumber}`.trim() } const buildText = (remaining, index = 0) => { const largeNumber = `${index > 1 ? getLargeNumber(index) + 'illion, ' : getLargeNumber(index)}` if (remaining < 1000) return `${buildThreeDigits(remaining)} ${largeNumber}` const layer = buildThreeDigits(remaining % 1000, index === 0) return `${buildText(Math.floor(remaining / 1000), index + 1)}${layer ? `${layer} ${largeNumber}` : ''}` } const buildLargeNumber = (numeral) => { const index = ~~(Math.log10(numeral) / 3) const topNumber = Math.round(numeral / Math.pow(10, index * 3)) const topThree = buildThreeDigits(topNumber) return `${topThree} ${getVeryLargeNumber(index)}illion` } function numToText(numeral) { if (numeral === 0) return 'zero' const text = numeral <= Number.MAX_SAFE_INTEGER ? buildText(Math.abs(numeral)).replace(/[\s,]*$/, '') : buildLargeNumber(Math.abs(numeral)) return numeral < 0 ? `minus ${text}` : `${text}` }
const getUnits = number => ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][number] || ''- const getUnits = number => ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][number]
- const getTens = (tens, units) => tens === 1
- ? ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'][units]
- : ['', '', 'twenty ', 'thirty ', 'fourty ', 'fifty ', 'sixty ', 'seventy ', 'eighty ', 'ninety '][tens] + getUnits(units)
const getLargeNumber = number => ['', 'thousand ', 'million ', 'billion ', 'trillion '][number]- const getLargeNumber = number => ['', 'thousand, ', 'm', 'b', 'tr', 'quadr', 'quint', 'sext', 'sept', 'oct', 'non'][number]
const convertThreeDigits = (numeral, more) => {- const getVeryLargeNumber = index => {
- if (index < 10) return getLargeNumber(index)
- const mappedIndex = (index - 9) / 3
- const prefix = ['', 'un', 'duo', 'tre', 'quattor', 'quin', 'sex', 'septen', 'octo', 'novem'][mappedIndex % 10]
- const suffix = ['dec', 'vigint', 'trigint', 'quadragint', 'quinquagint', 'sexagint', 'septuagint', 'octogint', 'nonagint'][~~(mappedIndex / 10)]
- return `${prefix}${suffix}`
- }
- const buildThreeDigits = (numeral, more) => {
- const tensNumber = getTens(~~((numeral % 100) / 10), (numeral % 100) % 10)
- const hundredsNumber = getUnits(~~(numeral / 100)) ? getUnits(~~(numeral / 100)) + ' hundred ' : ''
- const and = (hundredsNumber || more) && tensNumber ? 'and ' : ''
- return `${hundredsNumber}${and}${tensNumber}`.trim()
- }
- const buildText = (remaining, index = 0) => {
if (remaining < 1000) return `${convertThreeDigits(remaining)} ${getLargeNumber(index)}`return `${buildText(~~(remaining / 1000), index + 1)}${convertThreeDigits(remaining % 1000, remaining / 1000)}`- const largeNumber = `${index > 1 ? getLargeNumber(index) + 'illion, ' : getLargeNumber(index)}`
- if (remaining < 1000) return `${buildThreeDigits(remaining)} ${largeNumber}`
- const layer = buildThreeDigits(remaining % 1000, index === 0)
- return `${buildText(Math.floor(remaining / 1000), index + 1)}${layer ? `${layer} ${largeNumber}` : ''}`
- }
- const buildLargeNumber = (numeral) => {
- const index = ~~(Math.log10(numeral) / 3)
- const topNumber = Math.round(numeral / Math.pow(10, index * 3))
- const topThree = buildThreeDigits(topNumber)
- return `${topThree} ${getVeryLargeNumber(index)}illion`
- }
- function numToText(numeral) {
- if (numeral === 0) return 'zero'
const text = buildText(Math.abs(numeral)).trim()- const text = numeral <= Number.MAX_SAFE_INTEGER
- ? buildText(Math.abs(numeral)).replace(/[\s,]*$/, '')
- : buildLargeNumber(Math.abs(numeral))
- return numeral < 0 ? `minus ${text}` : `${text}`
- }
var expect = require("chai").expect; require("chai").should(); describe('numToText converts numbers to text', () => { describe('units', () => { [ { input: 0, actual: 'zero' }, { input: 1, actual: 'one' }, { input: 2, actual: 'two' }, { input: 3, actual: 'three' }, { input: 4, actual: 'four' }, { input: 5, actual: 'five' }, { input: 6, actual: 'six' }, { input: 7, actual: 'seven' }, { input: 8, actual: 'eight' }, { input: 9, actual: 'nine' } ].forEach(({ input, actual }) => { it(`should convert ${input} to ${actual}`, () => { expect(numToText(input)).to.equal(actual) }) }) }) describe('tens', () => { describe('teens', () => { [ { input: 10, actual: 'ten' }, { input: 11, actual: 'eleven' }, { input: 12, actual: 'twelve' }, { input: 13, actual: 'thirteen' }, { input: 14, actual: 'fourteen' }, { input: 15, actual: 'fifteen' }, { input: 16, actual: 'sixteen' }, { input: 17, actual: 'seventeen' }, { input: 18, actual: 'eighteen' }, { input: 19, actual: 'nineteen' } ].forEach(({ input, actual }) => { it(`should convert ${input} to ${actual}`, () => { expect(numToText(input)).to.equal(actual) }) }) }) describe('just the tens', () => { [ { input: 20, actual: 'twenty' }, { input: 30, actual: 'thirty' }, { input: 40, actual: 'fourty' }, { input: 50, actual: 'fifty' }, { input: 60, actual: 'sixty' }, { input: 70, actual: 'seventy' }, { input: 80, actual: 'eighty' }, { input: 90, actual: 'ninety' } ].forEach(({ input, actual }) => { it(`should convert ${input} to ${actual}`, () => { expect(numToText(input)).to.equal(actual) }) }) }) describe('tens and units', () => { it('should return twenty one when passed 21', () => { expect(numToText(21)).to.equal('twenty one') }) it('should return ninety nine when passed 99', () => { expect(numToText(99)).to.equal('ninety nine') }) }) }) describe('hundreds', () => { describe('just hundreds', () => { it('should return one hundred when passed 100', () => { expect(numToText(100)).to.equal('one hundred') }) it('should return two hundred when passed 200', () => { expect(numToText(200)).to.equal('two hundred') }) }) describe('any three digit number', () => { it('should return one hundred twenty three given 123', () => { expect(numToText(123)).to.equal('one hundred and twenty three') }) it('should return five hundred twelve given 512', () => { expect(numToText(512)).to.equal('five hundred and twelve') }) it('should return seven hundred one given 701', () => { expect(numToText(701)).to.equal('seven hundred and one') }) }) }) describe('thousands', () => { it('should return seven thousand, two hundred nineteen given 7219', () => { expect(numToText(7219)).to.equal('seven thousand, two hundred and nineteen') }) it('should return three hundred and four thousand, two hundred twenty one given 304221', () => { expect(numToText(304221)).to.equal('three hundred and four thousand, two hundred and twenty one') }) }) describe('very large numbers', () => { [ { input: 1000000, output: 'one million' }, { input: 452000000001, output: 'four hundred and fifty two billion, and one' }, { input: 452000000012, output: 'four hundred and fifty two billion, and twelve' }, { input: 452000000120, output: 'four hundred and fifty two billion, one hundred and twenty' }, { input: 452000000102, output: 'four hundred and fifty two billion, one hundred and two' }, { input: 100000000100, output: 'one hundred billion, one hundred' }, { input: Math.pow(10, 12), output: 'one trillion' }, { input: Math.pow(10, 15), output: 'one quadrillion' }, { input: 9007199254740991, output: 'nine quadrillion, seven trillion, one hundred and ninety nine billion, two hundred and fifty four million, seven hundred and fourty thousand, nine hundred and ninety one' }, { input: Number.MAX_SAFE_INTEGER, output: 'nine quadrillion, seven trillion, one hundred and ninety nine billion, two hundred and fifty four million, seven hundred and fourty thousand, nine hundred and ninety one' } ].forEach(({ input, output }) => { it(`should convert ${input} to ${output}`, () => { expect(numToText(input)).to.equal(output) }) }) }) describe('very very large numbers', () => { [ { input: 9007199254740992, output: 'nine quadrillion' }, { input: Number.MAX_SAFE_INTEGER + 1, output: 'nine quadrillion' }, { input: 9507199254740992, output: 'ten quadrillion' }, { input: 95071992547409920, output: 'ninety five quadrillion' }, { input: Math.pow(10, 18), output: 'one quintillion' }, { input: 317.5 * Math.pow(10, 36), output: 'three hundred and eighteen undecillion' } ].forEach(({ input, output }) => { it(`should convert ${input} to ${output}`, () => { expect(numToText(input)).to.equal(output) }) }) }) describe('negatives', () => { it('should do negative numbers', () => { expect(numToText(-1)).to.equal('minus one') }) }) })
- var expect = require("chai").expect;
- require("chai").should();
- describe('numToText converts numbers to text', () => {
- describe('units', () => {
- [
- { input: 0, actual: 'zero' },
- { input: 1, actual: 'one' },
- { input: 2, actual: 'two' },
- { input: 3, actual: 'three' },
- { input: 4, actual: 'four' },
- { input: 5, actual: 'five' },
- { input: 6, actual: 'six' },
- { input: 7, actual: 'seven' },
- { input: 8, actual: 'eight' },
- { input: 9, actual: 'nine' }
- ].forEach(({ input, actual }) => {
- it(`should convert ${input} to ${actual}`, () => {
- expect(numToText(input)).to.equal(actual)
- })
- })
- })
- describe('tens', () => {
- describe('teens', () => {
- [
- { input: 10, actual: 'ten' },
- { input: 11, actual: 'eleven' },
- { input: 12, actual: 'twelve' },
- { input: 13, actual: 'thirteen' },
- { input: 14, actual: 'fourteen' },
- { input: 15, actual: 'fifteen' },
- { input: 16, actual: 'sixteen' },
- { input: 17, actual: 'seventeen' },
- { input: 18, actual: 'eighteen' },
- { input: 19, actual: 'nineteen' }
- ].forEach(({ input, actual }) => {
- it(`should convert ${input} to ${actual}`, () => {
- expect(numToText(input)).to.equal(actual)
- })
- })
- })
- describe('just the tens', () => {
- [
- { input: 20, actual: 'twenty' },
- { input: 30, actual: 'thirty' },
- { input: 40, actual: 'fourty' },
- { input: 50, actual: 'fifty' },
- { input: 60, actual: 'sixty' },
- { input: 70, actual: 'seventy' },
- { input: 80, actual: 'eighty' },
- { input: 90, actual: 'ninety' }
- ].forEach(({ input, actual }) => {
- it(`should convert ${input} to ${actual}`, () => {
- expect(numToText(input)).to.equal(actual)
- })
- })
- })
- describe('tens and units', () => {
- it('should return twenty one when passed 21', () => {
- expect(numToText(21)).to.equal('twenty one')
- })
- it('should return ninety nine when passed 99', () => {
- expect(numToText(99)).to.equal('ninety nine')
- })
- })
- })
- describe('hundreds', () => {
- describe('just hundreds', () => {
- it('should return one hundred when passed 100', () => {
- expect(numToText(100)).to.equal('one hundred')
- })
- it('should return two hundred when passed 200', () => {
- expect(numToText(200)).to.equal('two hundred')
- })
- })
- describe('any three digit number', () => {
- it('should return one hundred twenty three given 123', () => {
- expect(numToText(123)).to.equal('one hundred and twenty three')
- })
- it('should return five hundred twelve given 512', () => {
- expect(numToText(512)).to.equal('five hundred and twelve')
- })
- it('should return seven hundred one given 701', () => {
- expect(numToText(701)).to.equal('seven hundred and one')
- })
- })
- })
- describe('thousands', () => {
it('should return seven thousand two hundred nineteen given 7219', () => {expect(numToText(7219)).to.equal('seven thousand two hundred and nineteen')- it('should return seven thousand, two hundred nineteen given 7219', () => {
- expect(numToText(7219)).to.equal('seven thousand, two hundred and nineteen')
- })
it('should return three hundred four thousand two hundred twenty one given 304221', () => {expect(numToText(304221)).to.equal('three hundred and four thousand two hundred and twenty one')- it('should return three hundred and four thousand, two hundred twenty one given 304221', () => {
- expect(numToText(304221)).to.equal('three hundred and four thousand, two hundred and twenty one')
- })
- })
- describe('very large numbers', () => {
- [
- { input: 1000000, output: 'one million' },
{ input: 452000000001, output: 'four hundred and fifty two billion and one' },{ input: 100000000100, output: 'one hundred billion one hundred' },- { input: 452000000001, output: 'four hundred and fifty two billion, and one' },
- { input: 452000000012, output: 'four hundred and fifty two billion, and twelve' },
- { input: 452000000120, output: 'four hundred and fifty two billion, one hundred and twenty' },
- { input: 452000000102, output: 'four hundred and fifty two billion, one hundred and two' },
- { input: 100000000100, output: 'one hundred billion, one hundred' },
- { input: Math.pow(10, 12), output: 'one trillion' },
- { input: Math.pow(10, 15), output: 'one quadrillion' },
- { input: 9007199254740991, output: 'nine quadrillion, seven trillion, one hundred and ninety nine billion, two hundred and fifty four million, seven hundred and fourty thousand, nine hundred and ninety one' },
- { input: Number.MAX_SAFE_INTEGER, output: 'nine quadrillion, seven trillion, one hundred and ninety nine billion, two hundred and fifty four million, seven hundred and fourty thousand, nine hundred and ninety one' }
- ].forEach(({ input, output }) => {
- it(`should convert ${input} to ${output}`, () => {
- expect(numToText(input)).to.equal(output)
- })
- })
- })
- describe('very very large numbers', () => {
- [
- { input: 9007199254740992, output: 'nine quadrillion' },
- { input: Number.MAX_SAFE_INTEGER + 1, output: 'nine quadrillion' },
- { input: 9507199254740992, output: 'ten quadrillion' },
- { input: 95071992547409920, output: 'ninety five quadrillion' },
- { input: Math.pow(10, 18), output: 'one quintillion' },
{ input: Math.pow(10, 21), output: 'one sextillion' },{ input: Math.pow(10, 24), output: 'one septillion' },{ input: Math.pow(10, 27), output: 'one octillion' },{ input: Math.pow(10, 30), output: 'one nonillion' },{ input: Math.pow(10, 33), output: 'one decillion' },{ input: Math.pow(10, 36), output: 'one undecillion' },{ input: Math.pow(10, 39), output: 'one duodecillion' },{ input: Math.pow(10, 42), output: 'one tredecillion' },{ input: Math.pow(10, 45), output: 'one quattuordecillion' },{ input: Math.pow(10, 48), output: 'one quindecillion' },{ input: Math.pow(10, 51), output: 'one sexdecillion' },{ input: Math.pow(10, 54), output: 'one septdecillion' },{ input: Math.pow(10, 57), output: 'one octdecillion' },{ input: Math.pow(10, 60), output: 'one novemdecillion' },{ input: Math.pow(10, 63), output: 'one vigintillion' },{ input: Math.pow(10, 303), output: 'one centillion' },- { input: 317.5 * Math.pow(10, 36), output: 'three hundred and eighteen undecillion' }
- ].forEach(({ input, output }) => {
- it(`should convert ${input} to ${output}`, () => {
- expect(numToText(input)).to.equal(output)
- })
- })
- })
- describe('negatives', () => {
- it('should do negative numbers', () => {
- expect(numToText(-1)).to.equal('minus one')
- })
- })
- })
Given any number (let's say up to the billions). It should convert that number into an English text string.
See the test cases for more information
const getUnits = number => ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][number] || ''
const getTens = (tens, units) => tens === 1
? ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'][units]
: ['', '', 'twenty ', 'thirty ', 'fourty ', 'fifty ', 'sixty ', 'seventy ', 'eighty ', 'ninety '][tens] + getUnits(units)
const getLargeNumber = number => ['', 'thousand ', 'million ', 'billion '][number]
const convertThreeDigits = (numeral, more) => {
const tensNumber = getTens(~~((numeral % 100) / 10), (numeral % 100) % 10)
const hundredsNumber = getUnits(~~(numeral / 100)) ? getUnits(~~(numeral / 100)) + ' hundred ' : ''
const and = (hundredsNumber || more) && tensNumber ? 'and ' : ''
return `${hundredsNumber}${and}${tensNumber}`.trim()
}
const buildText = (remaining, index = 0) => {
if (remaining < 1000) return `${convertThreeDigits(remaining)} ${getLargeNumber(index)}`
return `${buildText(~~(remaining / 1000), index + 1)}${convertThreeDigits(remaining % 1000, remaining / 1000)}`
}
function numToText(numeral) {
if (numeral === 0) return 'zero'
const text = buildText(Math.abs(numeral)).trim()
return numeral < 0 ? `minus ${text}` : `${text}`
}
var expect = require("chai").expect;
require("chai").should();
describe('numToText converts numbers to text', () => {
describe('units', () => {
[
{ input: 0, actual: 'zero' },
{ input: 1, actual: 'one' },
{ input: 2, actual: 'two' },
{ input: 3, actual: 'three' },
{ input: 4, actual: 'four' },
{ input: 5, actual: 'five' },
{ input: 6, actual: 'six' },
{ input: 7, actual: 'seven' },
{ input: 8, actual: 'eight' },
{ input: 9, actual: 'nine' }
].forEach(({ input, actual }) => {
it(`should convert ${input} to ${actual}`, () => {
expect(numToText(input)).to.equal(actual)
})
})
})
describe('tens', () => {
describe('teens', () => {
[
{ input: 10, actual: 'ten' },
{ input: 11, actual: 'eleven' },
{ input: 12, actual: 'twelve' },
{ input: 13, actual: 'thirteen' },
{ input: 14, actual: 'fourteen' },
{ input: 15, actual: 'fifteen' },
{ input: 16, actual: 'sixteen' },
{ input: 17, actual: 'seventeen' },
{ input: 18, actual: 'eighteen' },
{ input: 19, actual: 'nineteen' }
].forEach(({ input, actual }) => {
it(`should convert ${input} to ${actual}`, () => {
expect(numToText(input)).to.equal(actual)
})
})
})
describe('just the tens', () => {
[
{ input: 20, actual: 'twenty' },
{ input: 30, actual: 'thirty' },
{ input: 40, actual: 'fourty' },
{ input: 50, actual: 'fifty' },
{ input: 60, actual: 'sixty' },
{ input: 70, actual: 'seventy' },
{ input: 80, actual: 'eighty' },
{ input: 90, actual: 'ninety' }
].forEach(({ input, actual }) => {
it(`should convert ${input} to ${actual}`, () => {
expect(numToText(input)).to.equal(actual)
})
})
})
describe('tens and units', () => {
it('should return twenty one when passed 21', () => {
expect(numToText(21)).to.equal('twenty one')
})
it('should return ninety nine when passed 99', () => {
expect(numToText(99)).to.equal('ninety nine')
})
})
})
describe('hundreds', () => {
describe('just hundreds', () => {
it('should return one hundred when passed 100', () => {
expect(numToText(100)).to.equal('one hundred')
})
it('should return two hundred when passed 200', () => {
expect(numToText(200)).to.equal('two hundred')
})
})
describe('any three digit number', () => {
it('should return one hundred twenty three given 123', () => {
expect(numToText(123)).to.equal('one hundred and twenty three')
})
it('should return five hundred twelve given 512', () => {
expect(numToText(512)).to.equal('five hundred and twelve')
})
it('should return seven hundred one given 701', () => {
expect(numToText(701)).to.equal('seven hundred and one')
})
})
})
describe('thousands', () => {
it('should return seven thousand two hundred nineteen given 7219', () => {
expect(numToText(7219)).to.equal('seven thousand two hundred and nineteen')
})
it('should return three hundred four thousand two hundred twenty one given 304221', () => {
expect(numToText(304221)).to.equal('three hundred and four thousand two hundred and twenty one')
})
})
describe('very large numbers', () => {
[
{ input: 1000000, output: 'one million' },
{ input: 452000000001, output: 'four hundred and fifty two billion and one' },
{ input: 100000000100, output: 'one hundred billion one hundred' }
].forEach(({ input, output }) => {
it(`should convert ${input} to ${output}`, () => {
expect(numToText(input)).to.equal(output)
})
})
})
describe('negatives', () => {
it('should do negative numbers', () => {
expect(numToText(-1)).to.equal('minus one')
})
})
})