Gets the name of a number, even if it's stupidly big. Supersedes TheoryOfNekomata/number-name.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

278 lines
11 KiB

  1. import { describe, it, expect } from 'vitest';
  2. import { parse, stringify, systems } from '../../src';
  3. import { numberToExponential } from '../../src/exponent';
  4. const options = { system: systems.enUS };
  5. describe('numerica', () => {
  6. describe('group names', () => {
  7. describe('0-9', () => {
  8. it.each`
  9. ones | expected
  10. ${0} | ${'zero'}
  11. ${1} | ${'one'}
  12. ${2} | ${'two'}
  13. ${3} | ${'three'}
  14. ${4} | ${'four'}
  15. ${5} | ${'five'}
  16. ${6} | ${'six'}
  17. ${7} | ${'seven'}
  18. ${8} | ${'eight'}
  19. ${9} | ${'nine'}
  20. `('converts $ones to $expected', ({ ones, expected }: { ones: number, expected: string }) => {
  21. expect(stringify(ones, options)).toBe(expected);
  22. expect(parse(expected, { ...options, type: 'number' })).toBe(ones);
  23. });
  24. });
  25. describe('10-19', () => {
  26. it.each`
  27. tenPlusOnes | expected
  28. ${10} | ${'ten'}
  29. ${11} | ${'eleven'}
  30. ${12} | ${'twelve'}
  31. ${13} | ${'thirteen'}
  32. ${14} | ${'fourteen'}
  33. ${15} | ${'fifteen'}
  34. ${16} | ${'sixteen'}
  35. ${17} | ${'seventeen'}
  36. ${18} | ${'eighteen'}
  37. ${19} | ${'nineteen'}
  38. `('converts $tenPlusOnes to $expected', ({ tenPlusOnes, expected }: { tenPlusOnes: number, expected: string }) => {
  39. expect(stringify(tenPlusOnes, options)).toBe(expected);
  40. expect(parse(expected, { ...options, type: 'number' })).toBe(tenPlusOnes);
  41. });
  42. });
  43. describe.each`
  44. tensStart | tensEnd | tensBase
  45. ${20} | ${29} | ${'twenty'}
  46. ${30} | ${39} | ${'thirty'}
  47. ${40} | ${49} | ${'forty'}
  48. ${50} | ${59} | ${'fifty'}
  49. ${60} | ${69} | ${'sixty'}
  50. ${70} | ${79} | ${'seventy'}
  51. ${80} | ${89} | ${'eighty'}
  52. ${90} | ${99} | ${'ninety'}
  53. `('$tensStart-$tensEnd', ({
  54. tensStart, tensBase,
  55. }: { tensStart: number, tensBase: string }) => {
  56. it.each`
  57. value | expected
  58. ${tensStart} | ${tensBase}
  59. ${tensStart + 1} | ${`${tensBase} one`}
  60. ${tensStart + 2} | ${`${tensBase} two`}
  61. ${tensStart + 3} | ${`${tensBase} three`}
  62. ${tensStart + 4} | ${`${tensBase} four`}
  63. ${tensStart + 5} | ${`${tensBase} five`}
  64. ${tensStart + 6} | ${`${tensBase} six`}
  65. ${tensStart + 7} | ${`${tensBase} seven`}
  66. ${tensStart + 8} | ${`${tensBase} eight`}
  67. ${tensStart + 9} | ${`${tensBase} nine`}
  68. `('converts $value to $expected', ({ value, expected }: { value: number, expected: string }) => {
  69. expect(stringify(value, options)).toBe(expected);
  70. expect(parse(expected, { ...options, type: 'number' })).toBe(value);
  71. });
  72. });
  73. describe.each`
  74. hundredsStart | hundredsEnd | hundredsBase
  75. ${100} | ${199} | ${'one hundred'}
  76. ${200} | ${299} | ${'two hundred'}
  77. ${300} | ${399} | ${'three hundred'}
  78. ${400} | ${499} | ${'four hundred'}
  79. ${500} | ${599} | ${'five hundred'}
  80. ${600} | ${699} | ${'six hundred'}
  81. ${700} | ${799} | ${'seven hundred'}
  82. ${800} | ${899} | ${'eight hundred'}
  83. ${900} | ${999} | ${'nine hundred'}
  84. `('$hundredsStart-$hundredsEnd', ({
  85. hundredsStart, hundredsBase,
  86. }: { hundredsStart: number, hundredsBase: string }) => {
  87. describe(`${hundredsStart}-${hundredsStart + 9}`, () => {
  88. it.each`
  89. value | expected
  90. ${hundredsStart} | ${hundredsBase}
  91. ${hundredsStart + 1} | ${`${hundredsBase} one`}
  92. ${hundredsStart + 2} | ${`${hundredsBase} two`}
  93. ${hundredsStart + 3} | ${`${hundredsBase} three`}
  94. ${hundredsStart + 4} | ${`${hundredsBase} four`}
  95. ${hundredsStart + 5} | ${`${hundredsBase} five`}
  96. ${hundredsStart + 6} | ${`${hundredsBase} six`}
  97. ${hundredsStart + 7} | ${`${hundredsBase} seven`}
  98. ${hundredsStart + 8} | ${`${hundredsBase} eight`}
  99. ${hundredsStart + 9} | ${`${hundredsBase} nine`}
  100. `('converts $value to $expected', ({ value, expected }: { value: number, expected: string }) => {
  101. expect(stringify(value, options)).toBe(expected);
  102. expect(parse(expected, { ...options, type: 'number' })).toBe(value);
  103. });
  104. });
  105. describe(`${hundredsStart + 10}-${hundredsStart + 19}`, () => {
  106. it.each`
  107. value | expected
  108. ${hundredsStart + 10} | ${`${hundredsBase} ten`}
  109. ${hundredsStart + 11} | ${`${hundredsBase} eleven`}
  110. ${hundredsStart + 12} | ${`${hundredsBase} twelve`}
  111. ${hundredsStart + 13} | ${`${hundredsBase} thirteen`}
  112. ${hundredsStart + 14} | ${`${hundredsBase} fourteen`}
  113. ${hundredsStart + 15} | ${`${hundredsBase} fifteen`}
  114. ${hundredsStart + 16} | ${`${hundredsBase} sixteen`}
  115. ${hundredsStart + 17} | ${`${hundredsBase} seventeen`}
  116. ${hundredsStart + 18} | ${`${hundredsBase} eighteen`}
  117. ${hundredsStart + 19} | ${`${hundredsBase} nineteen`}
  118. `('converts $value to $expected', ({ value, expected }: { value: number, expected: string }) => {
  119. expect(stringify(value, options)).toBe(expected);
  120. expect(parse(expected, { ...options, type: 'number' })).toBe(value);
  121. });
  122. });
  123. describe.each`
  124. start | end | base
  125. ${20} | ${29} | ${'twenty'}
  126. ${30} | ${39} | ${'thirty'}
  127. ${40} | ${49} | ${'forty'}
  128. ${50} | ${59} | ${'fifty'}
  129. ${60} | ${69} | ${'sixty'}
  130. ${70} | ${79} | ${'seventy'}
  131. ${80} | ${89} | ${'eighty'}
  132. ${90} | ${99} | ${'ninety'}
  133. `('$start-$end', ({
  134. start, base,
  135. }: { start: number, base: string }) => {
  136. it.each`
  137. value | expected
  138. ${hundredsStart + start} | ${`${hundredsBase} ${base}`}
  139. ${hundredsStart + start + 1} | ${`${hundredsBase} ${base} one`}
  140. ${hundredsStart + start + 2} | ${`${hundredsBase} ${base} two`}
  141. ${hundredsStart + start + 3} | ${`${hundredsBase} ${base} three`}
  142. ${hundredsStart + start + 4} | ${`${hundredsBase} ${base} four`}
  143. ${hundredsStart + start + 5} | ${`${hundredsBase} ${base} five`}
  144. ${hundredsStart + start + 6} | ${`${hundredsBase} ${base} six`}
  145. ${hundredsStart + start + 7} | ${`${hundredsBase} ${base} seven`}
  146. ${hundredsStart + start + 8} | ${`${hundredsBase} ${base} eight`}
  147. ${hundredsStart + start + 9} | ${`${hundredsBase} ${base} nine`}
  148. `('converts $value to $expected', ({ value, expected }: { value: number, expected: string }) => {
  149. expect(stringify(value, options)).toBe(expected);
  150. expect(parse(expected, { ...options, type: 'number' })).toBe(value);
  151. });
  152. });
  153. });
  154. });
  155. it('converts 1000 to one thousand', () => {
  156. expect(stringify(1000, options)).toBe('one thousand');
  157. expect(parse('one thousand', { ...options, type: 'number' })).toBe(1000);
  158. });
  159. it('converts 10000 to ten thousand', () => {
  160. expect(stringify(10000, options)).toBe('ten thousand');
  161. expect(parse('ten thousand', { ...options, type: 'number' })).toBe(10000);
  162. });
  163. it('converts 100000 to one hundred thousand', () => {
  164. expect(stringify(100000, options)).toBe('one hundred thousand');
  165. expect(parse('one hundred thousand', { ...options, type: 'number' })).toBe(100000);
  166. });
  167. it('converts 123456 to one hundred twenty three thousand four hundred fifty six', () => {
  168. expect(stringify(123456, options)).toBe('one hundred twenty three thousand four hundred fifty six');
  169. expect(parse('one hundred twenty three thousand four hundred fifty six', { ...options, type: 'number' })).toBe(123456);
  170. });
  171. it.each`
  172. value | expected
  173. ${1e+6} | ${'one million'}
  174. ${1e+9} | ${'one billion'}
  175. ${1e+12} | ${'one trillion'}
  176. ${1e+15} | ${'one quadrillion'}
  177. ${1e+18} | ${'one quintillion'}
  178. ${1e+21} | ${'one sextillion'}
  179. ${1e+24} | ${'one septillion'}
  180. ${1e+27} | ${'one octillion'}
  181. ${1e+30} | ${'one nonillion'}
  182. `('converts $value to $expected', ({ value, expected }: { value: number, expected: string }) => {
  183. expect(stringify(value, options)).toBe(expected);
  184. expect(parse(expected, { ...options, type: 'number' })).toBe(value);
  185. });
  186. it.each`
  187. value | expected
  188. ${'1e+33'} | ${'one decillion'}
  189. ${'1e+36'} | ${'one undecillion'}
  190. ${'1e+39'} | ${'one duodecillion'}
  191. ${'1e+42'} | ${'one tredecillion'}
  192. ${'1e+45'} | ${'one quattuordecillion'}
  193. ${'1e+48'} | ${'one quindecillion'}
  194. ${'1e+51'} | ${'one sexdecillion'}
  195. ${'1e+54'} | ${'one septendecillion'}
  196. ${'1e+57'} | ${'one octodecillion'}
  197. ${'1e+60'} | ${'one novemdecillion'}
  198. `('converts $value to $expected', ({ value, expected }: { value: string, expected: string }) => {
  199. expect(stringify(value, options)).toBe(expected);
  200. expect(parse(expected, options)).toBe(value);
  201. });
  202. it.each`
  203. value | expected
  204. ${'1e+63'} | ${'one vigintillion'}
  205. ${'1e+66'} | ${'one unvigintillion'}
  206. ${'1e+69'} | ${'one duovigintillion'}
  207. ${'1e+72'} | ${'one trevigintillion'}
  208. ${'1e+75'} | ${'one quattuorvigintillion'}
  209. ${'1e+78'} | ${'one quinvigintillion'}
  210. ${'1e+81'} | ${'one sexvigintillion'}
  211. ${'1e+84'} | ${'one septenvigintillion'}
  212. ${'1e+87'} | ${'one octovigintillion'}
  213. ${'1e+90'} | ${'one novemvigintillion'}
  214. `('converts $value to $expected', ({ value, expected }: { value: string, expected: string }) => {
  215. expect(stringify(value, options)).toBe(expected);
  216. expect(parse(expected, options)).toBe(value);
  217. });
  218. it.each`
  219. value | expected
  220. ${'1e+93'} | ${'one trigintillion'}
  221. ${'1e+123'} | ${'one quadragintillion'}
  222. ${'1e+153'} | ${'one quinquagintillion'}
  223. ${'1e+183'} | ${'one sexagintillion'}
  224. ${'1e+213'} | ${'one septuagintillion'}
  225. ${'1e+243'} | ${'one octogintillion'}
  226. ${'1e+273'} | ${'one nonagintillion'}
  227. `('converts $value to $expected', ({ value, expected }: { value: string, expected: string }) => {
  228. expect(stringify(value, options)).toBe(expected);
  229. expect(parse(expected, options)).toBe(value);
  230. });
  231. it('converts values', () => {
  232. const exp1 = numberToExponential('123,456,789,012,345,678,901,234,567,890');
  233. //
  234. // one hundred twenty three octillion
  235. // four hundred fifty six septillion
  236. // seven hundred eighty nine sextillion
  237. // twelve quintillion
  238. // three hundred forty five quadrillion
  239. // six hundred seventy eight trillion
  240. // nine hundred one billion
  241. // two hundred thirty four million
  242. // five hundred sixty seven thousand
  243. // eight hundred ninety
  244. expect(parse(stringify('123456789012345678901234567890'))).toBe(exp1);
  245. const value2 = '1000005000000';
  246. const exp2 = numberToExponential(value2);
  247. expect(stringify(value2)).toBe('one trillion five million');
  248. expect(parse(stringify(value2))).toBe(exp2);
  249. const value3 = '12012';
  250. const exp3 = numberToExponential(value3);
  251. expect(stringify(value3)).toBe('twelve thousand twelve');
  252. expect(parse(stringify(value3))).toBe(exp3);
  253. const value4 = '12020';
  254. const exp4 = numberToExponential(value4);
  255. expect(stringify(value4)).toBe('twelve thousand twenty');
  256. expect(parse(stringify(value4))).toBe(exp4);
  257. });
  258. });