Browse Source

Start decoupling core code to locales

Ensure all three sample locales are correct with consistent rules. Also expanded the number type of hundreds to bigint to anticipate extra large numbers.
master
TheoryOfNekomata 3 years ago
parent
commit
a2ec5ea57c
70 changed files with 1322 additions and 1012 deletions
  1. +3
    -3
      package.json
  2. +19
    -16
      src/Converter.ts
  3. +6
    -7
      src/ConverterStream.ts
  4. +0
    -10
      src/NumberSystem.ts
  5. +0
    -14
      src/NumberSystemNameTable.ts
  6. +0
    -11
      src/common.ts
  7. +70
    -0
      src/common/index.ts
  8. +5
    -3
      src/systems/de/base/hundredTimes.ts
  9. +63
    -63
      src/systems/de/base/kilo/combiningPrefix.test.ts
  10. +34
    -23
      src/systems/de/base/kilo/combiningPrefix.ts
  11. +3
    -2
      src/systems/de/base/kilo/hundreds.ts
  12. +2
    -2
      src/systems/de/base/kilo/ones.test.ts
  13. +3
    -2
      src/systems/de/base/kilo/ones.ts
  14. +3
    -2
      src/systems/de/base/kilo/tens.ts
  15. +3
    -2
      src/systems/de/base/ones.ts
  16. +3
    -2
      src/systems/de/base/tenPlus.ts
  17. +3
    -2
      src/systems/de/base/tenTimes.ts
  18. +3
    -2
      src/systems/de/construct/tens.ts
  19. +129
    -0
      src/systems/de/getEuropeanLongKiloName.test.ts
  20. +23
    -0
      src/systems/de/getEuropeanLongKiloName.ts
  21. +18
    -0
      src/systems/de/getKiloCount.ts
  22. +0
    -129
      src/systems/de/getLongKiloName.test.ts
  23. +0
    -25
      src/systems/de/getLongKiloName.ts
  24. +14
    -0
      src/systems/de/index.ts
  25. +13
    -0
      src/systems/de/joinKilo.ts
  26. +0
    -92
      src/systems/de/names.json
  27. +19
    -0
      src/systems/de/names.ts
  28. +0
    -14
      src/systems/en.ts
  29. +3
    -2
      src/systems/en/base/hundredTimes.ts
  30. +63
    -63
      src/systems/en/base/kilo/combiningPrefix.test.ts
  31. +34
    -23
      src/systems/en/base/kilo/combiningPrefix.ts
  32. +3
    -2
      src/systems/en/base/kilo/hundreds.ts
  33. +2
    -2
      src/systems/en/base/kilo/ones.test.ts
  34. +3
    -2
      src/systems/en/base/kilo/ones.ts
  35. +3
    -2
      src/systems/en/base/kilo/tens.ts
  36. +3
    -2
      src/systems/en/base/ones.ts
  37. +3
    -2
      src/systems/en/base/tenPlus.ts
  38. +3
    -2
      src/systems/en/base/tenTimes.ts
  39. +2
    -1
      src/systems/en/construct/tens.ts
  40. +129
    -0
      src/systems/en/getEuropeanLongKiloName.test.ts
  41. +23
    -0
      src/systems/en/getEuropeanLongKiloName.ts
  42. +4
    -2
      src/systems/en/getKiloCount.ts
  43. +85
    -85
      src/systems/en/getLongKiloName.test.ts
  44. +8
    -8
      src/systems/en/getLongKiloName.ts
  45. +76
    -76
      src/systems/en/getShortKiloName.test.ts
  46. +8
    -8
      src/systems/en/getShortKiloName.ts
  47. +18
    -0
      src/systems/en/index.ts
  48. +5
    -0
      src/systems/en/joinKilo.ts
  49. +0
    -92
      src/systems/en/names.json
  50. +30
    -0
      src/systems/en/names.ts
  51. +4
    -3
      src/systems/tl/base/hundredTimes.ts
  52. +65
    -65
      src/systems/tl/base/kilo/combiningPrefix.test.ts
  53. +34
    -23
      src/systems/tl/base/kilo/combiningPrefix.ts
  54. +3
    -2
      src/systems/tl/base/kilo/hundreds.ts
  55. +2
    -2
      src/systems/tl/base/kilo/ones.test.ts
  56. +3
    -2
      src/systems/tl/base/kilo/ones.ts
  57. +3
    -2
      src/systems/tl/base/kilo/tens.ts
  58. +3
    -2
      src/systems/tl/base/ones.ts
  59. +4
    -3
      src/systems/tl/base/tenPlus.ts
  60. +3
    -2
      src/systems/tl/base/tenTimes.ts
  61. +3
    -2
      src/systems/tl/construct/tens.ts
  62. +9
    -9
      src/systems/tl/getKiloCount.test.ts
  63. +3
    -3
      src/systems/tl/getKiloCount.ts
  64. +120
    -0
      src/systems/tl/getShortKiloName.test.ts
  65. +20
    -0
      src/systems/tl/getShortKiloName.ts
  66. +14
    -0
      src/systems/tl/index.ts
  67. +18
    -0
      src/systems/tl/joinKilo.ts
  68. +0
    -92
      src/systems/tl/names.json
  69. +63
    -0
      src/systems/tl/names.ts
  70. +1
    -0
      tsconfig.json

+ 3
- 3
package.json View File

@@ -1,4 +1,7 @@
{
"name": "@theoryofnekomata/number-name",
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com> (https://modal.sh)",
"module": "dist/number-name.esm.js",
"version": "0.1.0",
"license": "MIT",
"main": "dist/index.js",
@@ -23,9 +26,6 @@
"pre-commit": "tsdx lint"
}
},
"name": "@theoryofnekomata/number-name",
"author": "TheoryOfNekomata <allan.crisostomo@outlook.com> (https://modal.sh)",
"module": "dist/number-name.esm.js",
"devDependencies": {
"@types/node": "^14.6.0",
"fast-check": "^2.1.0",


+ 19
- 16
src/Converter.ts View File

@@ -1,33 +1,36 @@
import NumberSystem from './NumberSystem'
import ConverterStream from './ConverterStream'
import { ReadStreamOptions, ConvertOptions } from './common'
import { ReadStreamOptions, ConvertOptions, NumberSystem, Digit } from './common'

export default class Converter {
constructor(private readonly system: NumberSystem) {}

convert(value: string | number | bigint, options: ConvertOptions) {
public convert = (value: string | number | bigint, options: ConvertOptions): string => {
let converted: string[] = []
switch (typeof value!) {
case 'string':
return ''
case 'bigint':
case 'number':
let current = value as number
let thousandPower = 0
while (current > 0) {
const hundreds = Math.floor((current % 1000) / 100)
const tens = Math.floor((current % 100) / 10)
const ones = Math.floor(current % 10)
return this.convert(BigInt(value), options)
case 'bigint':
let current = value as bigint
let thousandPower = 0n
while (current > 0n) {
const hundreds = Number(((current % 1000n) / 100n) % 10n) as Digit
const tens = Number(((current % 100n) / 10n) % 10n) as Digit
const ones = Number(current % 10n) as Digit

let kiloName: string | undefined
let kiloCount: string
if (!(ones === 0 && tens === 0 && hundreds === 0)) {
if (thousandPower > 0) {
if (thousandPower > 0n) {
const { scale = 'short' } = options
converted.unshift(this.system.getKiloName[scale!]!(thousandPower))
kiloName = this.system.getKiloName[scale!]!(thousandPower)
}
converted.unshift(this.system.getKiloCount(hundreds, tens, ones))
kiloCount = this.system.getKiloCount(hundreds, tens, ones)
converted.unshift(this.system.joinKilo(kiloCount, kiloName))
}

thousandPower = thousandPower + 1
current = Math.floor(current / 1000)
thousandPower = thousandPower + 1n
current = current / 1000n
}
return converted.join(' ')
default:


+ 6
- 7
src/ConverterStream.ts View File

@@ -1,16 +1,15 @@
import { Transform } from 'stream'
import NumberSystem from './NumberSystem'
import { ReadStreamOptions } from './common'
import { Digit, NumberSystem, ReadStreamOptions } from './common'

export default class ConverterStream extends Transform {
private thousandPower: number = 0
private thousandPower: bigint = 0n

constructor(private readonly system: NumberSystem, private readonly options: ReadStreamOptions) {
super()
this.thousandPower = 0
this.thousandPower = 0n
}

_transform(chunk: any, _encoding: BufferEncoding, callback: Function) {
_transform(chunk: Buffer, _encoding: BufferEncoding, callback: Function) {
const { scale, encoding } = this.options

const [ones = 0, tens = 0, hundreds = 0] = chunk
@@ -31,7 +30,7 @@ export default class ConverterStream extends Transform {
}
this.push(
this.system
.getKiloCount(hundreds, tens, ones)
.getKiloCount(hundreds as Digit, tens as Digit, ones as Digit)
.split('')
.reverse()
.join(''),
@@ -39,7 +38,7 @@ export default class ConverterStream extends Transform {
this.push(' ')
}

this.thousandPower = this.thousandPower + 1
this.thousandPower = this.thousandPower + 1n
callback()
}
}

+ 0
- 10
src/NumberSystem.ts View File

@@ -1,10 +0,0 @@
export type GetKiloCount = (hundreds: number, tens: number, ones: number) => string
export type GetKiloName = (thousandPower: number) => string

export default interface NumberSystem {
getKiloCount: GetKiloCount
getKiloName: {
short?: GetKiloName
long?: GetKiloName
}
}

+ 0
- 14
src/NumberSystemNameTable.ts View File

@@ -1,14 +0,0 @@
export default interface NumberSystemNameTable {
units: string[10]
tenPlus: string[10]
tenTimes: string[10]
hundred: string
thousand: string
kiloSpecialUnits: string[10]
kiloUnits: string[10]
kiloTens: string[10]
kiloHundreds: string[10]
kiloThousand: string
kiloEvenSuffix: string
kiloOddSuffix: string
}

+ 0
- 11
src/common.ts View File

@@ -1,11 +0,0 @@
export type Scale = 'long' | 'short'

export interface ConvertOptions {
scale?: Scale
}

export interface StreamOptions {
encoding?: BufferEncoding
}

export type ReadStreamOptions = ConvertOptions & StreamOptions

+ 70
- 0
src/common/index.ts View File

@@ -0,0 +1,70 @@
export type Scale = 'long' | 'short'

export interface ConvertOptions {
scale?: Scale
}

export interface StreamOptions {
encoding?: BufferEncoding
}

type NumberDigit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

type StringDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'

export type Digit = NumberDigit | StringDigit

export type ReadStreamOptions = ConvertOptions & StreamOptions

export type GetKiloCount = (hundreds: Digit, tens: Digit, ones: Digit) => string
export type GetKiloName = (thousandPower: bigint) => string
export type JoinKilo = (kiloCount: string, kiloName?: string) => string

export interface NumberSystem {
getKiloCount: GetKiloCount
getKiloName: {
short?: GetKiloName
long?: GetKiloName
europeanLong?: GetKiloName
}
joinKilo: JoinKilo
}

interface DigitString {
[0]: string
[1]: string
[2]: string
[3]: string
[4]: string
[5]: string
[6]: string
[7]: string
[8]: string
[9]: string
['0']: string
['1']: string
['2']: string
['3']: string
['4']: string
['5']: string
['6']: string
['7']: string
['8']: string
['9']: string
}

export interface NumberSystemNameTable {
units: DigitString
tenPlus: DigitString
tenTimes: DigitString
hundred: string
thousand: string
kiloSpecialUnits: DigitString
kiloUnits: DigitString
kiloTens: DigitString
kiloHundreds: DigitString
kiloThousand: string
kiloEvenSuffix: string
kiloOddSuffix: string
and: string
}

+ 5
- 3
src/systems/de/base/hundredTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface HundredTimes {
(x100: number): string
(x100: Digit): string
}

/**
@@ -9,6 +10,7 @@ interface HundredTimes {
* @param {number} x100 - The number in the hundreds place.
* @returns {string} The name of the number in the hundreds place.
*/
const hundredTimes: HundredTimes = (x100) => (x100 === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join(''))
const hundredTimes: HundredTimes = (x100) =>
Number(x100) === 0 ? NAMES.units[0] : [NAMES.units[x100], NAMES.hundred].join('')

export default hundredTimes

+ 63
- 63
src/systems/de/base/kilo/combiningPrefix.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof combiningPrefix).toBe('function')
})

it('should accept 4 arguments', () => {
expect(combiningPrefix).toHaveLength(4)
it('should accept a minimum of 3 arguments', () => {
expect(combiningPrefix).toHaveLength(3)
})

describe('on 0 in hundreds place', () => {
@@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => {
${8} | ${'8'} | ${'octi'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
expect(combiningPrefix(0n, 0, value)).toBe(name)
})
})

@@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => {
${8} | ${'octo' + tensName}
${9} | ${'novem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
expect(combiningPrefix(0n, tens, ones)).toBe(display)
})
})
})

describe.each`
hundreds | hundredsName
${1} | ${'cen'}
${2} | ${'duocen'}
${3} | ${'trecen'}
${4} | ${'quadringen'}
${5} | ${'quingen'}
${6} | ${'sescen'}
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
${1n} | ${'cen'}
${2n} | ${'duocen'}
${3n} | ${'trecen'}
${4n} | ${'quadringen'}
${5n} | ${'quingen'}
${6n} | ${'sescen'}
${7n} | ${'septingen'}
${8n} | ${'octingen'}
${9n} | ${'nongen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
@@ -105,43 +105,43 @@ describe.each`

describe.each`
hundredThousands | hundredThousandsName
${1} | ${'cen'}
${2} | ${'duocen'}
${3} | ${'trecen'}
${4} | ${'quadringen'}
${5} | ${'quingen'}
${6} | ${'sescen'}
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
${1n} | ${'cen'}
${2n} | ${'duocen'}
${3n} | ${'trecen'}
${4n} | ${'quadringen'}
${5n} | ${'quingen'}
${6n} | ${'sescen'}
${7n} | ${'septingen'}
${8n} | ${'octingen'}
${9n} | ${'nongen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
${1} | ${'dec'}
${2} | ${'vigin'}
${3} | ${'trigin'}
${4} | ${'quadragin'}
${5} | ${'quinquagin'}
${6} | ${'sexagin'}
${7} | ${'septuagin'}
${8} | ${'octogin'}
${9} | ${'nonagin'}
${0n} | ${''}
${1n} | ${'dec'}
${2n} | ${'vigin'}
${3n} | ${'trigin'}
${4n} | ${'quadragin'}
${5n} | ${'quinquagin'}
${6n} | ${'sexagin'}
${7n} | ${'septuagin'}
${8n} | ${'octogin'}
${9n} | ${'nonagin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'}
${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'}
${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'}
${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'}
${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'}
${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'}
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'}
${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'}
${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'}
${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'}
${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'}
${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'}
${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
@@ -149,30 +149,30 @@ describe.each`

test.each`
value | display | name
${1} | ${'1000000'} | ${'milliamilliati'}
${2} | ${'2000000'} | ${'duomilliamilliati'}
${3} | ${'3000000'} | ${'tremilliamilliati'}
${4} | ${'4000000'} | ${'quattuormilliamilliati'}
${5} | ${'5000000'} | ${'quinmilliamilliati'}
${6} | ${'6000000'} | ${'sexmilliamilliati'}
${7} | ${'7000000'} | ${'septenmilliamilliati'}
${8} | ${'8000000'} | ${'octomilliamilliati'}
${9} | ${'9000000'} | ${'novemmilliamilliati'}
${1n} | ${'1000000'} | ${'milliamilliati'}
${2n} | ${'2000000'} | ${'duomilliamilliati'}
${3n} | ${'3000000'} | ${'tremilliamilliati'}
${4n} | ${'4000000'} | ${'quattuormilliamilliati'}
${5n} | ${'5000000'} | ${'quinmilliamilliati'}
${6n} | ${'6000000'} | ${'sexmilliamilliati'}
${7n} | ${'7000000'} | ${'septenmilliamilliati'}
${8n} | ${'8000000'} | ${'octomilliamilliati'}
${9n} | ${'9000000'} | ${'novemmilliamilliati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name)
})

test.each`
value | display | name
${1} | ${'1001000'} | ${'milliamilliaunmilliati'}
${2} | ${'2002000'} | ${'duomilliamilliaduomilliati'}
${3} | ${'3003000'} | ${'tremilliamilliatremilliati'}
${4} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'}
${5} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'}
${6} | ${'6006000'} | ${'sexmilliamilliasexmilliati'}
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
${1n} | ${'1001000'} | ${'milliamilliaunmilliati'}
${2n} | ${'2002000'} | ${'duomilliamilliaduomilliati'}
${3n} | ${'3003000'} | ${'tremilliamilliatremilliati'}
${4n} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'}
${5n} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'}
${6n} | ${'6006000'} | ${'sexmilliamilliasexmilliati'}
${7n} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8n} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9n} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name)
})

+ 34
- 23
src/systems/de/base/kilo/combiningPrefix.ts View File

@@ -1,63 +1,74 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'
import ones from './ones'
import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
(kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string
}

const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => {
let currentKiloHundreds = kiloHundreds
let prefix = ''

const isMillia = kiloHundredsRaw >= 10
const isMillia = kiloHundreds >= 10n
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
kiloHundreds / 1000n,
(Number(kiloHundreds / 100n) % 10) as Digit,
(Number(kiloHundreds / 10n) % 10) as Digit,
kiloPower + 1n,
)
kiloHundreds = kiloHundredsRaw % 10
currentKiloHundreds = kiloHundreds % 10n
}

const hasHundreds = kiloHundreds > 0
const hasHundreds = currentKiloHundreds > 0n
if (hasHundreds) {
prefix += hundreds(kiloHundreds)
prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit)
}

const kiloTensNumber = Number(kiloTens)
const kiloOnesNumber = Number(kiloOnes)

if (
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) ||
((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) ||
(currentKiloHundreds === 0n &&
kiloTensNumber === 0 &&
kiloOnesNumber === 1 &&
prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
if (kiloPower === 0n && kiloOnesNumber) {
const special = currentKiloHundreds === 0n && kiloTensNumber === 0
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
if (special && [5, 6].includes(Number(kiloOnes))) {
prefix += 't'
}
}
if (kiloTens > 0) {
if (kiloTensNumber > 0) {
prefix += tens(kiloTens)
}

if (kiloPower > 0) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
if (kiloPower > 0n) {
if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) {
for (let p = 0n; p < kiloPower; p += 1n) {
prefix += NAMES.kiloThousand
}
}
return prefix
}

if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
if (
(currentKiloHundreds === 0n && kiloTensNumber > 1) ||
(currentKiloHundreds > 0n && kiloTensNumber !== 1) ||
kiloHundreds >= 10
) {
prefix += 't'
}
return prefix + 'i'


+ 3
- 2
src/systems/de/base/kilo/hundreds.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Hundreds {
(kiloHundreds: number): string
(kiloHundreds: Digit): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/de/base/kilo/ones.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 2 arguments', () => {
expect(ones).toHaveLength(2)
it('should accept a minimum of 1 argument', () => {
expect(ones).toHaveLength(1)
})

describe('on ordinary units', () => {


+ 3
- 2
src/systems/de/base/kilo/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Ones {
(kiloOnes: number, special: boolean): string
(kiloOnes: Digit, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) =>


+ 3
- 2
src/systems/de/base/kilo/tens.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Tens {
(kiloTens: number): string
(kiloTens: Digit): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 3
- 2
src/systems/de/base/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface Ones {
(x1: number): string
(x1: Digit): string
}

/**


+ 3
- 2
src/systems/de/base/tenPlus.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenPlus {
(ones: number): string
(ones: Digit): string
}

/**


+ 3
- 2
src/systems/de/base/tenTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenTimes {
(x10: number): string
(x10: Digit): string
}

/**


+ 3
- 2
src/systems/de/construct/tens.ts View File

@@ -1,10 +1,11 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'
import ones from '../base/ones'
import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string
(x10: Digit, x1: Digit): string
}

const tens: Tens = (x10, x1) => {


+ 129
- 0
src/systems/de/getEuropeanLongKiloName.test.ts View File

@@ -0,0 +1,129 @@
import getEuropeanLongKiloName from './getEuropeanLongKiloName'

it('should exist', () => {
expect(getEuropeanLongKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getEuropeanLongKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getEuropeanLongKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0n} | ${''}
${1n} | ${'tausend'}
${2n} | ${'million'}
${3n} | ${'milliard'}
${4n} | ${'billion'}
${5n} | ${'billiard'}
${6n} | ${'trillion'}
${7n} | ${'trilliard'}
${8n} | ${'quadrillion'}
${9n} | ${'quadrilliard'}
${10n} | ${'quintillion'}
${11n} | ${'quintilliard'}
${12n} | ${'sextillion'}
${13n} | ${'sextilliard'}
${14n} | ${'septillion'}
${15n} | ${'septilliard'}
${16n} | ${'octillion'}
${17n} | ${'octilliard'}
${18n} | ${'nonillion'}
${19n} | ${'nonilliard'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20n} | ${'decillion'}
${40n} | ${'vigintillion'}
${60n} | ${'trigintillion'}
${80n} | ${'quadragintillion'}
${100n} | ${'quinquagintillion'}
${120n} | ${'sexagintillion'}
${140n} | ${'septuagintillion'}
${160n} | ${'octogintillion'}
${180n} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200n} | ${'centillion'}
${400n} | ${'duocentillion'}
${600n} | ${'trecentillion'}
${800n} | ${'quadringentillion'}
${1000n} | ${'quingentillion'}
${1200n} | ${'sescentillion'}
${1400n} | ${'septingentillion'}
${1600n} | ${'octingentillion'}
${1800n} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000n} | ${'milliatillion'}
${4000n} | ${'duomilliatillion'}
${6000n} | ${'tremilliatillion'}
${8000n} | ${'quattuormilliatillion'}
${10000n} | ${'quinmilliatillion'}
${12000n} | ${'sexmilliatillion'}
${14000n} | ${'septenmilliatillion'}
${16000n} | ${'octomilliatillion'}
${18000n} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20000n} | ${'decmilliatillion'}
${40000n} | ${'viginmilliatillion'}
${60000n} | ${'triginmilliatillion'}
${80000n} | ${'quadraginmilliatillion'}
${100000n} | ${'quinquaginmilliatillion'}
${120000n} | ${'sexaginmilliatillion'}
${140000n} | ${'septuaginmilliatillion'}
${160000n} | ${'octoginmilliatillion'}
${180000n} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200000n} | ${'cenmilliatillion'}
${400000n} | ${'duocenmilliatillion'}
${600000n} | ${'trecenmilliatillion'}
${800000n} | ${'quadringenmilliatillion'}
${1000000n} | ${'quingenmilliatillion'}
${1200000n} | ${'sescenmilliatillion'}
${1400000n} | ${'septingenmilliatillion'}
${1600000n} | ${'octingenmilliatillion'}
${1800000n} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000000n} | ${'milliamilliatillion'}
${4000000n} | ${'duomilliamilliatillion'}
${6000000n} | ${'tremilliamilliatillion'}
${8000000n} | ${'quattuormilliamilliatillion'}
${10000000n} | ${'quinmilliamilliatillion'}
${12000000n} | ${'sexmilliamilliatillion'}
${14000000n} | ${'septenmilliamilliatillion'}
${16000000n} | ${'octomilliamilliatillion'}
${18000000n} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

+ 23
- 0
src/systems/de/getEuropeanLongKiloName.ts View File

@@ -0,0 +1,23 @@
import { Digit, GetKiloName } from '../../common'
import NAMES from './names'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getEuropeanLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0n) {
return ''
}
if (thousandPower === 1n) {
return NAMES.thousand
}
const kilo = thousandPower
const kiloHundreds = kilo / 2n / 100n
const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit
const kiloOnes = (Number(kilo / 2n) % 10) as Digit
const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes)

return thousandPower % 2n === 0n
? kiloCombiningPrefix + NAMES.kiloEvenSuffix
: kiloCombiningPrefix + NAMES.kiloOddSuffix
}

export default getEuropeanLongKiloName

+ 18
- 0
src/systems/de/getKiloCount.ts View File

@@ -0,0 +1,18 @@
import { GetKiloCount, Digit } from '../../common'
import constructTens from './construct/tens'
import hundredTimes from './base/hundredTimes'

const getKiloCount: GetKiloCount = (x100Raw, x10, x1) => {
const x100 = Number(BigInt(x100Raw) % 10n) as Digit
if (x100 < 1) {
return constructTens(x10, x1)
}

if (x10 === 0 && x1 === 0) {
return hundredTimes(x100)
}

return [hundredTimes(x100), constructTens(x10, x1)].join('')
}

export default getKiloCount

+ 0
- 129
src/systems/de/getLongKiloName.test.ts View File

@@ -1,129 +0,0 @@
import getKiloName from './getLongKiloName'

it('should exist', () => {
expect(getKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0} | ${''}
${1} | ${'Tausend'}
${2} | ${'Million'}
${3} | ${'Milliard'}
${4} | ${'Billion'}
${5} | ${'Billiard'}
${6} | ${'Trillion'}
${7} | ${'Trilliard'}
${8} | ${'Quadrillion'}
${9} | ${'Quadrilliard'}
${10} | ${'Quintillion'}
${11} | ${'Quintilliard'}
${12} | ${'Sextillion'}
${13} | ${'Sextilliard'}
${14} | ${'Septillion'}
${15} | ${'Septilliard'}
${16} | ${'Octillion'}
${17} | ${'Octilliard'}
${18} | ${'Nonillion'}
${19} | ${'Nonilliard'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20} | ${'Decillion'}
${40} | ${'Vigintillion'}
${60} | ${'Trigintillion'}
${80} | ${'Quadragintillion'}
${100} | ${'Quinquagintillion'}
${120} | ${'Sexagintillion'}
${140} | ${'Septuagintillion'}
${160} | ${'Octogintillion'}
${180} | ${'Nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200} | ${'Centillion'}
${400} | ${'Duocentillion'}
${600} | ${'Trecentillion'}
${800} | ${'Quadringentillion'}
${1000} | ${'Quingentillion'}
${1200} | ${'Sescentillion'}
${1400} | ${'Septingentillion'}
${1600} | ${'Octingentillion'}
${1800} | ${'Nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000} | ${'Milliatillion'}
${4000} | ${'Duomilliatillion'}
${6000} | ${'Tremilliatillion'}
${8000} | ${'Quattuormilliatillion'}
${10000} | ${'Quinmilliatillion'}
${12000} | ${'Sexmilliatillion'}
${14000} | ${'Septenmilliatillion'}
${16000} | ${'Octomilliatillion'}
${18000} | ${'Novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20000} | ${'Decmilliatillion'}
${40000} | ${'Viginmilliatillion'}
${60000} | ${'Triginmilliatillion'}
${80000} | ${'Quadraginmilliatillion'}
${100000} | ${'Quinquaginmilliatillion'}
${120000} | ${'Sexaginmilliatillion'}
${140000} | ${'Septuaginmilliatillion'}
${160000} | ${'Octoginmilliatillion'}
${180000} | ${'Nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200000} | ${'Cenmilliatillion'}
${400000} | ${'Duocenmilliatillion'}
${600000} | ${'Trecenmilliatillion'}
${800000} | ${'Quadringenmilliatillion'}
${1000000} | ${'Quingenmilliatillion'}
${1200000} | ${'Sescenmilliatillion'}
${1400000} | ${'Septingenmilliatillion'}
${1600000} | ${'Octingenmilliatillion'}
${1800000} | ${'Nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000000} | ${'Milliamilliatillion'}
${4000000} | ${'Duomilliamilliatillion'}
${6000000} | ${'Tremilliamilliatillion'}
${8000000} | ${'Quattuormilliamilliatillion'}
${10000000} | ${'Quinmilliamilliatillion'}
${12000000} | ${'Sexmilliamilliatillion'}
${14000000} | ${'Septenmilliamilliatillion'}
${16000000} | ${'Octomilliamilliatillion'}
${18000000} | ${'Novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
})

+ 0
- 25
src/systems/de/getLongKiloName.ts View File

@@ -1,25 +0,0 @@
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const capitalizeFirstLetter = (word: string) => word.slice(0, 1).toUpperCase() + word.slice(1)

const getLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
return ''
}
if (thousandPower === 1) {
return capitalizeFirstLetter(NAMES.thousand)
}
const kilo = thousandPower
const kiloHundreds = Math.floor(kilo / 2 / 100)
const kiloTens = Math.floor((kilo / 2 / 10) % 10)
const kiloOnes = Math.floor((kilo / 2) % 10)
const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes)

return capitalizeFirstLetter(
thousandPower % 2 === 0 ? kiloCombiningPrefix + NAMES.kiloEvenSuffix : kiloCombiningPrefix + NAMES.kiloOddSuffix,
)
}

export default getLongKiloName

+ 14
- 0
src/systems/de/index.ts View File

@@ -0,0 +1,14 @@
import { NumberSystem } from '../../common'
import getKiloCount from './getKiloCount'
import getEuropeanLongKiloName from './getEuropeanLongKiloName'
import joinKilo from './joinKilo'

const numberSystem: NumberSystem = {
getKiloCount,
getKiloName: {
europeanLong: getEuropeanLongKiloName,
},
joinKilo,
}

export default numberSystem

+ 13
- 0
src/systems/de/joinKilo.ts View File

@@ -0,0 +1,13 @@
import { JoinKilo } from '../../common'

const joinKilo: JoinKilo = (kiloCount, kiloName) =>
kiloName
? [
kiloCount,
' ',
kiloName.slice(0, 1).toUpperCase(), // capitalize kilo name
kiloName.slice(1),
].join('')
: kiloCount

export default joinKilo

+ 0
- 92
src/systems/de/names.json View File

@@ -1,92 +0,0 @@
{
"units": [
"zero",
"ein",
"zwei",
"drei",
"vier",
"fünf",
"sechs",
"sieben",
"acht",
"neun"
],
"tenPlus": [
"zehn",
"elf",
"zwölf",
"dreizehn",
"vierzehn",
"fünfzehn",
"sechzehn",
"siebzehn",
"achtzehn",
"neunzehn"
],
"tenTimes": [
"zero",
"zehn",
"zwanzig",
"dreißig",
"vierzig",
"fünfzig",
"sechzig",
"siebzig",
"achtzig",
"neunzig"
],
"hundred": "hundert",
"thousand": "tausend",
"kiloSpecialUnits": [
"",
"m",
"b",
"tr",
"quadr",
"quin",
"sex",
"sept",
"oct",
"non"
],
"kiloUnits": [
"",
"un",
"duo",
"tre",
"quattuor",
"quin",
"sex",
"septen",
"octo",
"novem"
],
"kiloTens": [
"",
"dec",
"vigin",
"trigin",
"quadragin",
"quinquagin",
"sexagin",
"septuagin",
"octogin",
"nonagin"
],
"kiloHundreds": [
"",
"cen",
"duocen",
"trecen",
"quadringen",
"quingen",
"sescen",
"septingen",
"octingen",
"nongen"
],
"kiloThousand": "millia",
"kiloEvenSuffix": "llion",
"kiloOddSuffix": "lliard",
"and": "und"
}

+ 19
- 0
src/systems/de/names.ts View File

@@ -0,0 +1,19 @@
import { NumberSystemNameTable } from '../../common'

const names: NumberSystemNameTable = {
units: ['zero', 'ein', 'zwei', 'drei', 'vier', 'fünf', 'sechs', 'sieben', 'acht', 'neun'],
tenPlus: ['zehn', 'elf', 'zwölf', 'dreizehn', 'vierzehn', 'fünfzehn', 'sechzehn', 'siebzehn', 'achtzehn', 'neunzehn'],
tenTimes: ['zero', 'zehn', 'zwanzig', 'dreißig', 'vierzig', 'fünfzig', 'sechzig', 'siebzig', 'achtzig', 'neunzig'],
hundred: 'hundert',
thousand: 'tausend',
kiloSpecialUnits: ['', 'm', 'b', 'tr', 'quadr', 'quin', 'sex', 'sept', 'oct', 'non'],
kiloUnits: ['', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem'],
kiloTens: ['', 'dec', 'vigin', 'trigin', 'quadragin', 'quinquagin', 'sexagin', 'septuagin', 'octogin', 'nonagin'],
kiloHundreds: ['', 'cen', 'duocen', 'trecen', 'quadringen', 'quingen', 'sescen', 'septingen', 'octingen', 'nongen'],
kiloThousand: 'millia',
kiloEvenSuffix: 'llion',
kiloOddSuffix: 'lliard',
and: 'und',
}

export default names

+ 0
- 14
src/systems/en.ts View File

@@ -1,14 +0,0 @@
import NumberSystem from '../NumberSystem'
import getKiloCount from './en/getKiloCount'
import getLongKiloName from './en/getLongKiloName'
import getShortKiloName from './en/getShortKiloName'

const en: NumberSystem = {
getKiloCount,
getKiloName: {
short: getShortKiloName,
long: getLongKiloName,
},
}

export default en

+ 3
- 2
src/systems/en/base/hundredTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface HundredTimes {
(x100: number): string
(x100: Digit): string
}

/**


+ 63
- 63
src/systems/en/base/kilo/combiningPrefix.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof combiningPrefix).toBe('function')
})

it('should accept 4 arguments', () => {
expect(combiningPrefix).toHaveLength(4)
it('should accept a minimum of 3 arguments', () => {
expect(combiningPrefix).toHaveLength(3)
})

describe('on 0 in hundreds place', () => {
@@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => {
${8} | ${'8'} | ${'octi'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
expect(combiningPrefix(0n, 0, value)).toBe(name)
})
})

@@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => {
${8} | ${'octo' + tensName}
${9} | ${'novem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
expect(combiningPrefix(0n, tens, ones)).toBe(display)
})
})
})

describe.each`
hundreds | hundredsName
${1} | ${'cen'}
${2} | ${'duocen'}
${3} | ${'trecen'}
${4} | ${'quadringen'}
${5} | ${'quingen'}
${6} | ${'sescen'}
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
${1n} | ${'cen'}
${2n} | ${'duocen'}
${3n} | ${'trecen'}
${4n} | ${'quadringen'}
${5n} | ${'quingen'}
${6n} | ${'sescen'}
${7n} | ${'septingen'}
${8n} | ${'octingen'}
${9n} | ${'nongen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
@@ -105,43 +105,43 @@ describe.each`

describe.each`
hundredThousands | hundredThousandsName
${1} | ${'cen'}
${2} | ${'duocen'}
${3} | ${'trecen'}
${4} | ${'quadringen'}
${5} | ${'quingen'}
${6} | ${'sescen'}
${7} | ${'septingen'}
${8} | ${'octingen'}
${9} | ${'nongen'}
${1n} | ${'cen'}
${2n} | ${'duocen'}
${3n} | ${'trecen'}
${4n} | ${'quadringen'}
${5n} | ${'quingen'}
${6n} | ${'sescen'}
${7n} | ${'septingen'}
${8n} | ${'octingen'}
${9n} | ${'nongen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
${1} | ${'dec'}
${2} | ${'vigin'}
${3} | ${'trigin'}
${4} | ${'quadragin'}
${5} | ${'quinquagin'}
${6} | ${'sexagin'}
${7} | ${'septuagin'}
${8} | ${'octogin'}
${9} | ${'nonagin'}
${0n} | ${''}
${1n} | ${'dec'}
${2n} | ${'vigin'}
${3n} | ${'trigin'}
${4n} | ${'quadragin'}
${5n} | ${'quinquagin'}
${6n} | ${'sexagin'}
${7n} | ${'septuagin'}
${8n} | ${'octogin'}
${9n} | ${'nonagin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'}
${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'}
${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'}
${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'}
${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'}
${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'}
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milliati'}
${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milliati'}
${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duo' + tenThousandsName + 'milliati'}
${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milliati'}
${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'quattuor' + tenThousandsName + 'milliati'}
${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'quin' + tenThousandsName + 'milliati'}
${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'sex' + tenThousandsName + 'milliati'}
${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milliati'}
${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'octo' + tenThousandsName + 'milliati'}
${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'novem' + tenThousandsName + 'milliati'}
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
@@ -149,30 +149,30 @@ describe.each`

test.each`
value | display | name
${1} | ${'1000000'} | ${'milliamilliati'}
${2} | ${'2000000'} | ${'duomilliamilliati'}
${3} | ${'3000000'} | ${'tremilliamilliati'}
${4} | ${'4000000'} | ${'quattuormilliamilliati'}
${5} | ${'5000000'} | ${'quinmilliamilliati'}
${6} | ${'6000000'} | ${'sexmilliamilliati'}
${7} | ${'7000000'} | ${'septenmilliamilliati'}
${8} | ${'8000000'} | ${'octomilliamilliati'}
${9} | ${'9000000'} | ${'novemmilliamilliati'}
${1n} | ${'1000000'} | ${'milliamilliati'}
${2n} | ${'2000000'} | ${'duomilliamilliati'}
${3n} | ${'3000000'} | ${'tremilliamilliati'}
${4n} | ${'4000000'} | ${'quattuormilliamilliati'}
${5n} | ${'5000000'} | ${'quinmilliamilliati'}
${6n} | ${'6000000'} | ${'sexmilliamilliati'}
${7n} | ${'7000000'} | ${'septenmilliamilliati'}
${8n} | ${'8000000'} | ${'octomilliamilliati'}
${9n} | ${'9000000'} | ${'novemmilliamilliati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name)
})

test.each`
value | display | name
${1} | ${'1001000'} | ${'milliamilliaunmilliati'}
${2} | ${'2002000'} | ${'duomilliamilliaduomilliati'}
${3} | ${'3003000'} | ${'tremilliamilliatremilliati'}
${4} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'}
${5} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'}
${6} | ${'6006000'} | ${'sexmilliamilliasexmilliati'}
${7} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
${1n} | ${'1001000'} | ${'milliamilliaunmilliati'}
${2n} | ${'2002000'} | ${'duomilliamilliaduomilliati'}
${3n} | ${'3003000'} | ${'tremilliamilliatremilliati'}
${4n} | ${'4004000'} | ${'quattuormilliamilliaquattuormilliati'}
${5n} | ${'5005000'} | ${'quinmilliamilliaquinmilliati'}
${6n} | ${'6006000'} | ${'sexmilliamilliasexmilliati'}
${7n} | ${'7007000'} | ${'septenmilliamilliaseptenmilliati'}
${8n} | ${'8008000'} | ${'octomilliamilliaoctomilliati'}
${9n} | ${'9009000'} | ${'novemmilliamillianovemmilliati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name)
})

+ 34
- 23
src/systems/en/base/kilo/combiningPrefix.ts View File

@@ -1,63 +1,74 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'
import ones from './ones'
import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
(kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string
}

const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => {
let currentKiloHundreds = kiloHundreds
let prefix = ''

const isMillia = kiloHundredsRaw >= 10
const isMillia = kiloHundreds >= 10n
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
kiloHundreds / 1000n,
(Number(kiloHundreds / 100n) % 10) as Digit,
(Number(kiloHundreds / 10n) % 10) as Digit,
kiloPower + 1n,
)
kiloHundreds = kiloHundredsRaw % 10
currentKiloHundreds = kiloHundreds % 10n
}

const hasHundreds = kiloHundreds > 0
const hasHundreds = currentKiloHundreds > 0n
if (hasHundreds) {
prefix += hundreds(kiloHundreds)
prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit)
}

const kiloTensNumber = Number(kiloTens)
const kiloOnesNumber = Number(kiloOnes)

if (
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) ||
((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) ||
(currentKiloHundreds === 0n &&
kiloTensNumber === 0 &&
kiloOnesNumber === 1 &&
prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
if (kiloPower === 0n && kiloOnesNumber) {
const special = currentKiloHundreds === 0n && kiloTensNumber === 0
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
if (special && [5, 6].includes(Number(kiloOnes))) {
prefix += 't'
}
}
if (kiloTens > 0) {
if (kiloTensNumber > 0) {
prefix += tens(kiloTens)
}

if (kiloPower > 0) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
if (kiloPower > 0n) {
if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) {
for (let p = 0n; p < kiloPower; p += 1n) {
prefix += NAMES.kiloThousand
}
}
return prefix
}

if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
if (
(currentKiloHundreds === 0n && kiloTensNumber > 1) ||
(currentKiloHundreds > 0n && kiloTensNumber !== 1) ||
kiloHundreds >= 10
) {
prefix += 't'
}
return prefix + 'i'


+ 3
- 2
src/systems/en/base/kilo/hundreds.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Hundreds {
(kiloHundreds: number): string
(kiloHundreds: Digit): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/en/base/kilo/ones.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 2 arguments', () => {
expect(ones).toHaveLength(2)
it('should accept a minimum of 1 argument', () => {
expect(ones).toHaveLength(1)
})

describe('on ordinary units', () => {


+ 3
- 2
src/systems/en/base/kilo/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Ones {
(kiloOnes: number, special: boolean): string
(kiloOnes: Digit, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) =>


+ 3
- 2
src/systems/en/base/kilo/tens.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Tens {
(kiloTens: number): string
(kiloTens: Digit): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 3
- 2
src/systems/en/base/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface Ones {
(x1: number): string
(x1: Digit): string
}

/**


+ 3
- 2
src/systems/en/base/tenPlus.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenPlus {
(ones: number): string
(ones: Digit): string
}

/**


+ 3
- 2
src/systems/en/base/tenTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenTimes {
(x10: number): string
(x10: Digit): string
}

/**


+ 2
- 1
src/systems/en/construct/tens.ts View File

@@ -1,9 +1,10 @@
import { Digit } from '../../../common'
import ones from '../base/ones'
import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string
(x10: Digit, x1: Digit): string
}

const tens: Tens = (x10, x1) => {


+ 129
- 0
src/systems/en/getEuropeanLongKiloName.test.ts View File

@@ -0,0 +1,129 @@
import getEuropeanLongKiloName from './getEuropeanLongKiloName'

it('should exist', () => {
expect(getEuropeanLongKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getEuropeanLongKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getEuropeanLongKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0n} | ${''}
${1n} | ${'thousand'}
${2n} | ${'million'}
${3n} | ${'milliard'}
${4n} | ${'billion'}
${5n} | ${'billiard'}
${6n} | ${'trillion'}
${7n} | ${'trilliard'}
${8n} | ${'quadrillion'}
${9n} | ${'quadrilliard'}
${10n} | ${'quintillion'}
${11n} | ${'quintilliard'}
${12n} | ${'sextillion'}
${13n} | ${'sextilliard'}
${14n} | ${'septillion'}
${15n} | ${'septilliard'}
${16n} | ${'octillion'}
${17n} | ${'octilliard'}
${18n} | ${'nonillion'}
${19n} | ${'nonilliard'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20n} | ${'decillion'}
${40n} | ${'vigintillion'}
${60n} | ${'trigintillion'}
${80n} | ${'quadragintillion'}
${100n} | ${'quinquagintillion'}
${120n} | ${'sexagintillion'}
${140n} | ${'septuagintillion'}
${160n} | ${'octogintillion'}
${180n} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200n} | ${'centillion'}
${400n} | ${'duocentillion'}
${600n} | ${'trecentillion'}
${800n} | ${'quadringentillion'}
${1000n} | ${'quingentillion'}
${1200n} | ${'sescentillion'}
${1400n} | ${'septingentillion'}
${1600n} | ${'octingentillion'}
${1800n} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000n} | ${'milliatillion'}
${4000n} | ${'duomilliatillion'}
${6000n} | ${'tremilliatillion'}
${8000n} | ${'quattuormilliatillion'}
${10000n} | ${'quinmilliatillion'}
${12000n} | ${'sexmilliatillion'}
${14000n} | ${'septenmilliatillion'}
${16000n} | ${'octomilliatillion'}
${18000n} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20000n} | ${'decmilliatillion'}
${40000n} | ${'viginmilliatillion'}
${60000n} | ${'triginmilliatillion'}
${80000n} | ${'quadraginmilliatillion'}
${100000n} | ${'quinquaginmilliatillion'}
${120000n} | ${'sexaginmilliatillion'}
${140000n} | ${'septuaginmilliatillion'}
${160000n} | ${'octoginmilliatillion'}
${180000n} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200000n} | ${'cenmilliatillion'}
${400000n} | ${'duocenmilliatillion'}
${600000n} | ${'trecenmilliatillion'}
${800000n} | ${'quadringenmilliatillion'}
${1000000n} | ${'quingenmilliatillion'}
${1200000n} | ${'sescenmilliatillion'}
${1400000n} | ${'septingenmilliatillion'}
${1600000n} | ${'octingenmilliatillion'}
${1800000n} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000000n} | ${'milliamilliatillion'}
${4000000n} | ${'duomilliamilliatillion'}
${6000000n} | ${'tremilliamilliatillion'}
${8000000n} | ${'quattuormilliamilliatillion'}
${10000000n} | ${'quinmilliamilliatillion'}
${12000000n} | ${'sexmilliamilliatillion'}
${14000000n} | ${'septenmilliamilliatillion'}
${16000000n} | ${'octomilliamilliatillion'}
${18000000n} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getEuropeanLongKiloName(thousandPower)).toBe(name)
})

+ 23
- 0
src/systems/en/getEuropeanLongKiloName.ts View File

@@ -0,0 +1,23 @@
import { Digit, GetKiloName } from '../../common'
import NAMES from './names'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getEuropeanLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0n) {
return ''
}
if (thousandPower === 1n) {
return NAMES.thousand
}
const kilo = thousandPower
const kiloHundreds = kilo / 2n / 100n
const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit
const kiloOnes = (Number(kilo / 2n) % 10) as Digit
const kiloCombiningPrefix = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes)

return thousandPower % 2n === 0n
? kiloCombiningPrefix + NAMES.kiloEvenSuffix
: kiloCombiningPrefix + NAMES.kiloOddSuffix
}

export default getEuropeanLongKiloName

+ 4
- 2
src/systems/en/getKiloCount.ts View File

@@ -1,8 +1,9 @@
import { GetKiloCount } from '../../NumberSystem'
import { GetKiloCount, Digit } from '../../common'
import constructTens from './construct/tens'
import hundredTimes from './base/hundredTimes'

const getKiloCount: GetKiloCount = (x100, x10, x1) => {
const getKiloCount: GetKiloCount = (x100Raw, x10, x1) => {
const x100 = Number(BigInt(x100Raw) % 10n) as Digit
if (x100 < 1) {
return constructTens(x10, x1)
}
@@ -10,6 +11,7 @@ const getKiloCount: GetKiloCount = (x100, x10, x1) => {
if (x10 === 0 && x1 === 0) {
return hundredTimes(x100)
}

return [hundredTimes(x100), constructTens(x10, x1)].join(' ')
}



+ 85
- 85
src/systems/en/getLongKiloName.test.ts View File

@@ -1,129 +1,129 @@
import getKiloName from './getLongKiloName'
import getLongKiloName from './getLongKiloName'

it('should exist', () => {
expect(getKiloName).toBeDefined()
expect(getLongKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getKiloName).toBe('function')
expect(typeof getLongKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getKiloName).toHaveLength(1)
expect(getLongKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0} | ${''}
${1} | ${'thousand'}
${2} | ${'million'}
${3} | ${'thousand million'}
${4} | ${'billion'}
${5} | ${'thousand billion'}
${6} | ${'trillion'}
${7} | ${'thousand trillion'}
${8} | ${'quadrillion'}
${9} | ${'thousand quadrillion'}
${10} | ${'quintillion'}
${11} | ${'thousand quintillion'}
${12} | ${'sextillion'}
${13} | ${'thousand sextillion'}
${14} | ${'septillion'}
${15} | ${'thousand septillion'}
${16} | ${'octillion'}
${17} | ${'thousand octillion'}
${18} | ${'nonillion'}
${19} | ${'thousand nonillion'}
${0n} | ${''}
${1n} | ${'thousand'}
${2n} | ${'million'}
${3n} | ${'thousand million'}
${4n} | ${'billion'}
${5n} | ${'thousand billion'}
${6n} | ${'trillion'}
${7n} | ${'thousand trillion'}
${8n} | ${'quadrillion'}
${9n} | ${'thousand quadrillion'}
${10n} | ${'quintillion'}
${11n} | ${'thousand quintillion'}
${12n} | ${'sextillion'}
${13n} | ${'thousand sextillion'}
${14n} | ${'septillion'}
${15n} | ${'thousand septillion'}
${16n} | ${'octillion'}
${17n} | ${'thousand octillion'}
${18n} | ${'nonillion'}
${19n} | ${'thousand nonillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20} | ${'decillion'}
${40} | ${'vigintillion'}
${60} | ${'trigintillion'}
${80} | ${'quadragintillion'}
${100} | ${'quinquagintillion'}
${120} | ${'sexagintillion'}
${140} | ${'septuagintillion'}
${160} | ${'octogintillion'}
${180} | ${'nonagintillion'}
${20n} | ${'decillion'}
${40n} | ${'vigintillion'}
${60n} | ${'trigintillion'}
${80n} | ${'quadragintillion'}
${100n} | ${'quinquagintillion'}
${120n} | ${'sexagintillion'}
${140n} | ${'septuagintillion'}
${160n} | ${'octogintillion'}
${180n} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200} | ${'centillion'}
${400} | ${'duocentillion'}
${600} | ${'trecentillion'}
${800} | ${'quadringentillion'}
${1000} | ${'quingentillion'}
${1200} | ${'sescentillion'}
${1400} | ${'septingentillion'}
${1600} | ${'octingentillion'}
${1800} | ${'nongentillion'}
${200n} | ${'centillion'}
${400n} | ${'duocentillion'}
${600n} | ${'trecentillion'}
${800n} | ${'quadringentillion'}
${1000n} | ${'quingentillion'}
${1200n} | ${'sescentillion'}
${1400n} | ${'septingentillion'}
${1600n} | ${'octingentillion'}
${1800n} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000} | ${'milliatillion'}
${4000} | ${'duomilliatillion'}
${6000} | ${'tremilliatillion'}
${8000} | ${'quattuormilliatillion'}
${10000} | ${'quinmilliatillion'}
${12000} | ${'sexmilliatillion'}
${14000} | ${'septenmilliatillion'}
${16000} | ${'octomilliatillion'}
${18000} | ${'novemmilliatillion'}
${2000n} | ${'milliatillion'}
${4000n} | ${'duomilliatillion'}
${6000n} | ${'tremilliatillion'}
${8000n} | ${'quattuormilliatillion'}
${10000n} | ${'quinmilliatillion'}
${12000n} | ${'sexmilliatillion'}
${14000n} | ${'septenmilliatillion'}
${16000n} | ${'octomilliatillion'}
${18000n} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${20000} | ${'decmilliatillion'}
${40000} | ${'viginmilliatillion'}
${60000} | ${'triginmilliatillion'}
${80000} | ${'quadraginmilliatillion'}
${100000} | ${'quinquaginmilliatillion'}
${120000} | ${'sexaginmilliatillion'}
${140000} | ${'septuaginmilliatillion'}
${160000} | ${'octoginmilliatillion'}
${180000} | ${'nonaginmilliatillion'}
${20000n} | ${'decmilliatillion'}
${40000n} | ${'viginmilliatillion'}
${60000n} | ${'triginmilliatillion'}
${80000n} | ${'quadraginmilliatillion'}
${100000n} | ${'quinquaginmilliatillion'}
${120000n} | ${'sexaginmilliatillion'}
${140000n} | ${'septuaginmilliatillion'}
${160000n} | ${'octoginmilliatillion'}
${180000n} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${200000} | ${'cenmilliatillion'}
${400000} | ${'duocenmilliatillion'}
${600000} | ${'trecenmilliatillion'}
${800000} | ${'quadringenmilliatillion'}
${1000000} | ${'quingenmilliatillion'}
${1200000} | ${'sescenmilliatillion'}
${1400000} | ${'septingenmilliatillion'}
${1600000} | ${'octingenmilliatillion'}
${1800000} | ${'nongenmilliatillion'}
${200000n} | ${'cenmilliatillion'}
${400000n} | ${'duocenmilliatillion'}
${600000n} | ${'trecenmilliatillion'}
${800000n} | ${'quadringenmilliatillion'}
${1000000n} | ${'quingenmilliatillion'}
${1200000n} | ${'sescenmilliatillion'}
${1400000n} | ${'septingenmilliatillion'}
${1600000n} | ${'octingenmilliatillion'}
${1800000n} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${2000000} | ${'milliamilliatillion'}
${4000000} | ${'duomilliamilliatillion'}
${6000000} | ${'tremilliamilliatillion'}
${8000000} | ${'quattuormilliamilliatillion'}
${10000000} | ${'quinmilliamilliatillion'}
${12000000} | ${'sexmilliamilliatillion'}
${14000000} | ${'septenmilliamilliatillion'}
${16000000} | ${'octomilliamilliatillion'}
${18000000} | ${'novemmilliamilliatillion'}
${2000000n} | ${'milliamilliatillion'}
${4000000n} | ${'duomilliamilliatillion'}
${6000000n} | ${'tremilliamilliatillion'}
${8000000n} | ${'quattuormilliamilliatillion'}
${10000000n} | ${'quinmilliamilliatillion'}
${12000000n} | ${'sexmilliamilliatillion'}
${14000000n} | ${'septenmilliamilliatillion'}
${16000000n} | ${'octomilliamilliatillion'}
${18000000n} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getLongKiloName(thousandPower)).toBe(name)
})

+ 8
- 8
src/systems/en/getLongKiloName.ts View File

@@ -1,21 +1,21 @@
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import { Digit, GetKiloName } from '../../common'
import NAMES from './names'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getLongKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
if (thousandPower === 0n) {
return ''
}
if (thousandPower === 1) {
if (thousandPower === 1n) {
return NAMES.thousand
}
const kilo = thousandPower
const kiloHundreds = Math.floor(kilo / 2 / 100)
const kiloTens = Math.floor((kilo / 2 / 10) % 10)
const kiloOnes = Math.floor((kilo / 2) % 10)
const kiloHundreds = kilo / 2n / 100n
const kiloTens = (Number(kilo / 2n / 10n) % 10) as Digit
const kiloOnes = (Number(kilo / 2n) % 10) as Digit
const baseKiloName = getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix

return thousandPower % 2 === 0 ? baseKiloName : NAMES.thousand + ' ' + baseKiloName
return thousandPower % 2n === 0n ? baseKiloName : NAMES.thousand + ' ' + baseKiloName
}

export default getLongKiloName

+ 76
- 76
src/systems/en/getShortKiloName.test.ts View File

@@ -1,120 +1,120 @@
import getKiloName from './getShortKiloName'
import getShortKiloName from './getShortKiloName'

it('should exist', () => {
expect(getKiloName).toBeDefined()
expect(getShortKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getKiloName).toBe('function')
expect(typeof getShortKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getKiloName).toHaveLength(1)
expect(getShortKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0} | ${''}
${1} | ${'thousand'}
${2} | ${'million'}
${3} | ${'billion'}
${4} | ${'trillion'}
${5} | ${'quadrillion'}
${6} | ${'quintillion'}
${7} | ${'sextillion'}
${8} | ${'septillion'}
${9} | ${'octillion'}
${10} | ${'nonillion'}
${0n} | ${''}
${1n} | ${'thousand'}
${2n} | ${'million'}
${3n} | ${'billion'}
${4n} | ${'trillion'}
${5n} | ${'quadrillion'}
${6n} | ${'quintillion'}
${7n} | ${'sextillion'}
${8n} | ${'septillion'}
${9n} | ${'octillion'}
${10n} | ${'nonillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${11} | ${'decillion'}
${21} | ${'vigintillion'}
${31} | ${'trigintillion'}
${41} | ${'quadragintillion'}
${51} | ${'quinquagintillion'}
${61} | ${'sexagintillion'}
${71} | ${'septuagintillion'}
${81} | ${'octogintillion'}
${91} | ${'nonagintillion'}
${11n} | ${'decillion'}
${21n} | ${'vigintillion'}
${31n} | ${'trigintillion'}
${41n} | ${'quadragintillion'}
${51n} | ${'quinquagintillion'}
${61n} | ${'sexagintillion'}
${71n} | ${'septuagintillion'}
${81n} | ${'octogintillion'}
${91n} | ${'nonagintillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${101} | ${'centillion'}
${201} | ${'duocentillion'}
${301} | ${'trecentillion'}
${401} | ${'quadringentillion'}
${501} | ${'quingentillion'}
${601} | ${'sescentillion'}
${701} | ${'septingentillion'}
${801} | ${'octingentillion'}
${901} | ${'nongentillion'}
${101n} | ${'centillion'}
${201n} | ${'duocentillion'}
${301n} | ${'trecentillion'}
${401n} | ${'quadringentillion'}
${501n} | ${'quingentillion'}
${601n} | ${'sescentillion'}
${701n} | ${'septingentillion'}
${801n} | ${'octingentillion'}
${901n} | ${'nongentillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${1001} | ${'milliatillion'}
${2001} | ${'duomilliatillion'}
${3001} | ${'tremilliatillion'}
${4001} | ${'quattuormilliatillion'}
${5001} | ${'quinmilliatillion'}
${6001} | ${'sexmilliatillion'}
${7001} | ${'septenmilliatillion'}
${8001} | ${'octomilliatillion'}
${9001} | ${'novemmilliatillion'}
${1001n} | ${'milliatillion'}
${2001n} | ${'duomilliatillion'}
${3001n} | ${'tremilliatillion'}
${4001n} | ${'quattuormilliatillion'}
${5001n} | ${'quinmilliatillion'}
${6001n} | ${'sexmilliatillion'}
${7001n} | ${'septenmilliatillion'}
${8001n} | ${'octomilliatillion'}
${9001n} | ${'novemmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${10001} | ${'decmilliatillion'}
${20001} | ${'viginmilliatillion'}
${30001} | ${'triginmilliatillion'}
${40001} | ${'quadraginmilliatillion'}
${50001} | ${'quinquaginmilliatillion'}
${60001} | ${'sexaginmilliatillion'}
${70001} | ${'septuaginmilliatillion'}
${80001} | ${'octoginmilliatillion'}
${90001} | ${'nonaginmilliatillion'}
${10001n} | ${'decmilliatillion'}
${20001n} | ${'viginmilliatillion'}
${30001n} | ${'triginmilliatillion'}
${40001n} | ${'quadraginmilliatillion'}
${50001n} | ${'quinquaginmilliatillion'}
${60001n} | ${'sexaginmilliatillion'}
${70001n} | ${'septuaginmilliatillion'}
${80001n} | ${'octoginmilliatillion'}
${90001n} | ${'nonaginmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${100001} | ${'cenmilliatillion'}
${200001} | ${'duocenmilliatillion'}
${300001} | ${'trecenmilliatillion'}
${400001} | ${'quadringenmilliatillion'}
${500001} | ${'quingenmilliatillion'}
${600001} | ${'sescenmilliatillion'}
${700001} | ${'septingenmilliatillion'}
${800001} | ${'octingenmilliatillion'}
${900001} | ${'nongenmilliatillion'}
${100001n} | ${'cenmilliatillion'}
${200001n} | ${'duocenmilliatillion'}
${300001n} | ${'trecenmilliatillion'}
${400001n} | ${'quadringenmilliatillion'}
${500001n} | ${'quingenmilliatillion'}
${600001n} | ${'sescenmilliatillion'}
${700001n} | ${'septingenmilliatillion'}
${800001n} | ${'octingenmilliatillion'}
${900001n} | ${'nongenmilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${1000001} | ${'milliamilliatillion'}
${2000001} | ${'duomilliamilliatillion'}
${3000001} | ${'tremilliamilliatillion'}
${4000001} | ${'quattuormilliamilliatillion'}
${5000001} | ${'quinmilliamilliatillion'}
${6000001} | ${'sexmilliamilliatillion'}
${7000001} | ${'septenmilliamilliatillion'}
${8000001} | ${'octomilliamilliatillion'}
${9000001} | ${'novemmilliamilliatillion'}
${1000001n} | ${'milliamilliatillion'}
${2000001n} | ${'duomilliamilliatillion'}
${3000001n} | ${'tremilliamilliatillion'}
${4000001n} | ${'quattuormilliamilliatillion'}
${5000001n} | ${'quinmilliamilliatillion'}
${6000001n} | ${'sexmilliamilliatillion'}
${7000001n} | ${'septenmilliamilliatillion'}
${8000001n} | ${'octomilliamilliatillion'}
${9000001n} | ${'novemmilliamilliatillion'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getKiloName(thousandPower)).toBe(name)
expect(getShortKiloName(thousandPower)).toBe(name)
})

+ 8
- 8
src/systems/en/getShortKiloName.ts View File

@@ -1,18 +1,18 @@
import { GetKiloName } from '../../NumberSystem'
import NAMES from './names.json'
import { GetKiloName, Digit } from '../../common'
import NAMES from './names'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0) {
if (thousandPower === 0n) {
return ''
}
if (thousandPower === 1) {
if (thousandPower === 1n) {
return NAMES.thousand
}
const kilo = thousandPower - 1
const kiloHundreds = Math.floor(kilo / 100)
const kiloTens = Math.floor((kilo / 10) % 10)
const kiloOnes = Math.floor(kilo % 10)
const kilo = thousandPower - 1n
const kiloHundreds = kilo / 100n
const kiloTens = (Number(kilo / 10n) % 10) as Digit
const kiloOnes = (Number(kilo) % 10) as Digit

return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix
}


+ 18
- 0
src/systems/en/index.ts View File

@@ -0,0 +1,18 @@
import { NumberSystem } from '../../common'
import getKiloCount from './getKiloCount'
import getLongKiloName from './getLongKiloName'
import getEuropeanLongKiloName from './getEuropeanLongKiloName'
import getShortKiloName from './getShortKiloName'
import joinKilo from './joinKilo'

const numberSystem: NumberSystem = {
getKiloCount,
getKiloName: {
short: getShortKiloName,
long: getLongKiloName,
europeanLong: getEuropeanLongKiloName,
},
joinKilo,
}

export default numberSystem

+ 5
- 0
src/systems/en/joinKilo.ts View File

@@ -0,0 +1,5 @@
import { JoinKilo } from '../../common'

const joinKilo: JoinKilo = (kiloCount, kiloName) => (kiloName ? [kiloCount, kiloName].join(' ') : kiloCount)

export default joinKilo

+ 0
- 92
src/systems/en/names.json View File

@@ -1,92 +0,0 @@
{
"units": [
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine"
],
"tenPlus": [
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
"eighteen",
"nineteen"
],
"tenTimes": [
"zero",
"ten",
"twenty",
"thirty",
"forty",
"fifty",
"sixty",
"seventy",
"eighty",
"ninety"
],
"hundred": "hundred",
"thousand": "thousand",
"kiloSpecialUnits": [
"",
"m",
"b",
"tr",
"quadr",
"quin",
"sex",
"sept",
"oct",
"non"
],
"kiloUnits": [
"",
"un",
"duo",
"tre",
"quattuor",
"quin",
"sex",
"septen",
"octo",
"novem"
],
"kiloTens": [
"",
"dec",
"vigin",
"trigin",
"quadragin",
"quinquagin",
"sexagin",
"septuagin",
"octogin",
"nonagin"
],
"kiloHundreds": [
"",
"cen",
"duocen",
"trecen",
"quadringen",
"quingen",
"sescen",
"septingen",
"octingen",
"nongen"
],
"kiloThousand": "millia",
"kiloEvenSuffix": "llion",
"kiloOddSuffix": "lliard",
"and": "and"
}

+ 30
- 0
src/systems/en/names.ts View File

@@ -0,0 +1,30 @@
import { NumberSystemNameTable } from '../../common'

const names: NumberSystemNameTable = {
units: ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'],
tenPlus: [
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
],
tenTimes: ['zero', 'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'],
hundred: 'hundred',
thousand: 'thousand',
kiloSpecialUnits: ['', 'm', 'b', 'tr', 'quadr', 'quin', 'sex', 'sept', 'oct', 'non'],
kiloUnits: ['', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem'],
kiloTens: ['', 'dec', 'vigin', 'trigin', 'quadragin', 'quinquagin', 'sexagin', 'septuagin', 'octogin', 'nonagin'],
kiloHundreds: ['', 'cen', 'duocen', 'trecen', 'quadringen', 'quingen', 'sescen', 'septingen', 'octingen', 'nongen'],
kiloThousand: 'millia',
kiloEvenSuffix: 'llion',
kiloOddSuffix: 'lliard',
and: 'and',
}

export default names

+ 4
- 3
src/systems/tl/base/hundredTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface HundredTimes {
(x100: number): string
(x100: Digit): string
}

/**
@@ -19,7 +20,7 @@ const hundredTimes: HundredTimes = (x100) => {
let infix: string
let hundredSuffixCombining: string

switch (x100) {
switch (Number(x100)) {
case 1:
hundredFactorCombining = hundredFactor.slice(1)
infix = 'n'


+ 65
- 65
src/systems/tl/base/kilo/combiningPrefix.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof combiningPrefix).toBe('function')
})

it('should accept 4 arguments', () => {
expect(combiningPrefix).toHaveLength(4)
it('should accept a minimum of 3 arguments', () => {
expect(combiningPrefix).toHaveLength(3)
})

describe('on 0 in hundreds place', () => {
@@ -26,7 +26,7 @@ describe('on 0 in hundreds place', () => {
${8} | ${'8'} | ${'okti'}
${9} | ${'9'} | ${'noni'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(0, 0, value)).toBe(name)
expect(combiningPrefix(0n, 0, value)).toBe(name)
})
})

@@ -55,22 +55,22 @@ describe('on 0 in hundreds place', () => {
${8} | ${'okto' + tensName}
${9} | ${'nobem' + tensName}
`(`should return "$display" for ${tens}$ones`, ({ ones, display }) => {
expect(combiningPrefix(0, tens, ones)).toBe(display)
expect(combiningPrefix(0n, tens, ones)).toBe(display)
})
})
})

describe.each`
hundreds | hundredsName
${1} | ${'sen'}
${2} | ${'duwosen'}
${3} | ${'tresen'}
${4} | ${'kuwadringhen'}
${5} | ${'kuwinghen'}
${6} | ${'sesen'}
${7} | ${'septinghen'}
${8} | ${'oktinghen'}
${9} | ${'nonghen'}
${1n} | ${'sen'}
${2n} | ${'duwosen'}
${3n} | ${'tresen'}
${4n} | ${'kuwadringhen'}
${5n} | ${'kuwinghen'}
${6n} | ${'sesen'}
${7n} | ${'septinghen'}
${8n} | ${'oktinghen'}
${9n} | ${'nonghen'}
`('on $hundreds in hundreds place', ({ hundreds, hundredsName }) => {
describe.each`
tens | tensName
@@ -105,74 +105,74 @@ describe.each`

describe.each`
hundredThousands | hundredThousandsName
${1} | ${'sen'}
${2} | ${'duwosen'}
${3} | ${'tresen'}
${4} | ${'kuwadringhen'}
${5} | ${'kuwinghen'}
${6} | ${'sesen'}
${7} | ${'septinghen'}
${8} | ${'oktinghen'}
${9} | ${'nonghen'}
${1n} | ${'sen'}
${2n} | ${'duwosen'}
${3n} | ${'tresen'}
${4n} | ${'kuwadringhen'}
${5n} | ${'kuwinghen'}
${6n} | ${'sesen'}
${7n} | ${'septinghen'}
${8n} | ${'oktinghen'}
${9n} | ${'nonghen'}
`('on $hundredThousands in hundred thousands place', ({ hundredThousands, hundredThousandsName }) => {
describe.each`
tenThousands | tenThousandsName
${0} | ${''}
${1} | ${'des'}
${2} | ${'bihin'}
${3} | ${'trihin'}
${4} | ${'kuwadrahin'}
${5} | ${'kuwinkuwahin'}
${6} | ${'seksahin'}
${7} | ${'septuwahin'}
${8} | ${'oktohin'}
${9} | ${'nonahin'}
${0n} | ${''}
${1n} | ${'des'}
${2n} | ${'bihin'}
${3n} | ${'trihin'}
${4n} | ${'kuwadrahin'}
${5n} | ${'kuwinkuwahin'}
${6n} | ${'seksahin'}
${7n} | ${'septuwahin'}
${8n} | ${'oktohin'}
${9n} | ${'nonahin'}
`('on $tenThousands in ten thousands place', ({ tenThousands, tenThousandsName }) => {
test.each`
thousands | display | name
${0} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'}
${1000} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milyati'}
${2000} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duwo' + tenThousandsName + 'milyati'}
${3000} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milyati'}
${4000} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'kuwatuwor' + tenThousandsName + 'milyati'}
${5000} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'kuwin' + tenThousandsName + 'milyati'}
${6000} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'seks' + tenThousandsName + 'milyati'}
${7000} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'}
${8000} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'}
${9000} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'}
${0n} | ${hundredThousands + '' + tenThousands + '0000'} | ${hundredThousandsName + tenThousandsName + 'milyati'}
${1000n} | ${hundredThousands + '' + tenThousands + '1000'} | ${hundredThousandsName + 'un' + tenThousandsName + 'milyati'}
${2000n} | ${hundredThousands + '' + tenThousands + '2000'} | ${hundredThousandsName + 'duwo' + tenThousandsName + 'milyati'}
${3000n} | ${hundredThousands + '' + tenThousands + '3000'} | ${hundredThousandsName + 'tre' + tenThousandsName + 'milyati'}
${4000n} | ${hundredThousands + '' + tenThousands + '4000'} | ${hundredThousandsName + 'kuwatuwor' + tenThousandsName + 'milyati'}
${5000n} | ${hundredThousands + '' + tenThousands + '5000'} | ${hundredThousandsName + 'kuwin' + tenThousandsName + 'milyati'}
${6000n} | ${hundredThousands + '' + tenThousands + '6000'} | ${hundredThousandsName + 'seks' + tenThousandsName + 'milyati'}
${7000n} | ${hundredThousands + '' + tenThousands + '7000'} | ${hundredThousandsName + 'septen' + tenThousandsName + 'milyati'}
${8000n} | ${hundredThousands + '' + tenThousands + '8000'} | ${hundredThousandsName + 'okto' + tenThousandsName + 'milyati'}
${9000n} | ${hundredThousands + '' + tenThousands + '9000'} | ${hundredThousandsName + 'nobem' + tenThousandsName + 'milyati'}
`(`should return "$name" for $display`, ({ thousands, name }) => {
const kiloHundreds = hundredThousands * 1000 + tenThousands * 100 + thousands / 100
const kiloHundreds = hundredThousands * 1000n + tenThousands * 100n + thousands / 100n
expect(combiningPrefix(kiloHundreds, 0, 0)).toBe(name)
})
})
})

it.each`
test.each`
value | display | name
${1} | ${'1000000'} | ${'milyamilyati'}
${2} | ${'2000000'} | ${'duwomilyamilyati'}
${3} | ${'3000000'} | ${'tremilyamilyati'}
${4} | ${'4000000'} | ${'kuwatuwormilyamilyati'}
${5} | ${'5000000'} | ${'kuwinmilyamilyati'}
${6} | ${'6000000'} | ${'seksmilyamilyati'}
${7} | ${'7000000'} | ${'septenmilyamilyati'}
${8} | ${'8000000'} | ${'oktomilyamilyati'}
${9} | ${'9000000'} | ${'nobemmilyamilyati'}
${1n} | ${'1000000'} | ${'milyamilyati'}
${2n} | ${'2000000'} | ${'duwomilyamilyati'}
${3n} | ${'3000000'} | ${'tremilyamilyati'}
${4n} | ${'4000000'} | ${'kuwatuwormilyamilyati'}
${5n} | ${'5000000'} | ${'kuwinmilyamilyati'}
${6n} | ${'6000000'} | ${'seksmilyamilyati'}
${7n} | ${'7000000'} | ${'septenmilyamilyati'}
${8n} | ${'8000000'} | ${'oktomilyamilyati'}
${9n} | ${'9000000'} | ${'nobemmilyamilyati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10000, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10000n, 0, 0)).toBe(name)
})

it.each`
test.each`
value | display | name
${1} | ${'1001000'} | ${'milyamilyaunmilyati'}
${2} | ${'2002000'} | ${'duwomilyamilyaduwomilyati'}
${3} | ${'3003000'} | ${'tremilyamilyatremilyati'}
${4} | ${'4004000'} | ${'kuwatuwormilyamilyakuwatuwormilyati'}
${5} | ${'5005000'} | ${'kuwinmilyamilyakuwinmilyati'}
${6} | ${'6006000'} | ${'seksmilyamilyaseksmilyati'}
${7} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'}
${8} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'}
${9} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'}
${1n} | ${'1001000'} | ${'milyamilyaunmilyati'}
${2n} | ${'2002000'} | ${'duwomilyamilyaduwomilyati'}
${3n} | ${'3003000'} | ${'tremilyamilyatremilyati'}
${4n} | ${'4004000'} | ${'kuwatuwormilyamilyakuwatuwormilyati'}
${5n} | ${'5005000'} | ${'kuwinmilyamilyakuwinmilyati'}
${6n} | ${'6006000'} | ${'seksmilyamilyaseksmilyati'}
${7n} | ${'7007000'} | ${'septenmilyamilyaseptenmilyati'}
${8n} | ${'8008000'} | ${'oktomilyamilyaoktomilyati'}
${9n} | ${'9009000'} | ${'nobemmilyamilyanobemmilyati'}
`('should return "$name" on $display', ({ value, name }) => {
expect(combiningPrefix(value * 10010, 0, 0)).toBe(name)
expect(combiningPrefix(value * 10010n, 0, 0)).toBe(name)
})

+ 34
- 23
src/systems/tl/base/kilo/combiningPrefix.ts View File

@@ -1,63 +1,74 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'
import ones from './ones'
import tens from './tens'
import hundreds from './hundreds'

interface CombiningPrefix {
(kiloHundreds: number, kiloTens: number, kiloOnes: number, kiloPower?: number): string
(kiloHundreds: bigint, kiloTens: Digit, kiloOnes: Digit, kiloPower?: bigint): string
}

const combiningPrefix: CombiningPrefix = (kiloHundredsRaw, kiloTens, kiloOnes, kiloPower = 0) => {
let kiloHundreds = kiloHundredsRaw
const combiningPrefix: CombiningPrefix = (kiloHundreds, kiloTens, kiloOnes, kiloPower = 0n) => {
let currentKiloHundreds = kiloHundreds
let prefix = ''

const isMillia = kiloHundredsRaw >= 10
const isMillia = kiloHundreds >= 10n
if (isMillia) {
prefix += combiningPrefix(
Math.floor(kiloHundredsRaw / 1000),
Math.floor((kiloHundredsRaw / 100) % 10),
Math.floor((kiloHundredsRaw / 10) % 10),
kiloPower + 1,
kiloHundreds / 1000n,
(Number(kiloHundreds / 100n) % 10) as Digit,
(Number(kiloHundreds / 10n) % 10) as Digit,
kiloPower + 1n,
)
kiloHundreds = kiloHundredsRaw % 10
currentKiloHundreds = kiloHundreds % 10n
}

const hasHundreds = kiloHundreds > 0
const hasHundreds = currentKiloHundreds > 0n
if (hasHundreds) {
prefix += hundreds(kiloHundreds)
prefix += hundreds(Number(currentKiloHundreds % 10n) as Digit)
}

const kiloTensNumber = Number(kiloTens)
const kiloOnesNumber = Number(kiloOnes)

if (
kiloPower > 0 &&
((kiloHundreds === 0 && kiloTens === 0 && kiloOnes > 1) ||
((kiloHundreds > 0 || kiloTens > 0) && kiloOnes > 0) ||
(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 1 && prefix.endsWith(NAMES.kiloThousand)))
((currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber > 1) ||
((currentKiloHundreds > 0n || kiloTensNumber > 0) && kiloOnesNumber > 0) ||
(currentKiloHundreds === 0n &&
kiloTensNumber === 0 &&
kiloOnesNumber === 1 &&
prefix.endsWith(NAMES.kiloThousand)))
) {
// http://www.isthe.com/chongo/tech/math/number/howhigh.html
// Section: Titanic size numbers < 10^3000003
prefix += ones(kiloOnes, false)
}
if (kiloPower === 0 && kiloOnes > 0) {
const special = kiloHundreds === 0 && kiloTens === 0
if (kiloPower === 0n && kiloOnesNumber) {
const special = currentKiloHundreds === 0n && kiloTensNumber === 0
prefix += ones(kiloOnes, special)
if (special && [5, 6].includes(kiloOnes)) {
if (special && [5, 6].includes(Number(kiloOnes))) {
prefix += 't'
}
}
if (kiloTens > 0) {
if (kiloTensNumber > 0) {
prefix += tens(kiloTens)
}

if (kiloPower > 0) {
if (!(kiloHundreds === 0 && kiloTens === 0 && kiloOnes === 0)) {
for (let p = 0; p < kiloPower; p += 1) {
if (kiloPower > 0n) {
if (!(currentKiloHundreds === 0n && kiloTensNumber === 0 && kiloOnesNumber === 0)) {
for (let p = 0n; p < kiloPower; p += 1n) {
prefix += NAMES.kiloThousand
}
}
return prefix
}

if ((kiloHundreds === 0 && kiloTens > 1) || (kiloHundreds > 0 && kiloTens !== 1) || kiloHundredsRaw >= 10) {
if (
(currentKiloHundreds === 0n && kiloTensNumber > 1) ||
(currentKiloHundreds > 0n && kiloTensNumber !== 1) ||
kiloHundreds >= 10
) {
prefix += 't'
}
return prefix + 'i'


+ 3
- 2
src/systems/tl/base/kilo/hundreds.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Hundreds {
(kiloHundreds: number): string
(kiloHundreds: Digit): string
}

const hundreds: Hundreds = (kiloHundreds) => NAMES.kiloHundreds[kiloHundreds]


+ 2
- 2
src/systems/tl/base/kilo/ones.test.ts View File

@@ -8,8 +8,8 @@ it('should be a callable', () => {
expect(typeof ones).toBe('function')
})

it('should accept 2 arguments', () => {
expect(ones).toHaveLength(2)
it('should accept a minimum of 1 argument', () => {
expect(ones).toHaveLength(1)
})

describe('on ordinary units', () => {


+ 3
- 2
src/systems/tl/base/kilo/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Ones {
(kiloOnes: number, special: boolean): string
(kiloOnes: Digit, special: boolean): string
}

const ones: Ones = (kiloOnes, special = false) =>


+ 3
- 2
src/systems/tl/base/kilo/tens.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../../names.json'
import { Digit } from '../../../../common'
import NAMES from '../../names'

interface Tens {
(kiloTens: number): string
(kiloTens: Digit): string
}

const tens: Tens = (kiloTens) => NAMES.kiloTens[kiloTens]


+ 3
- 2
src/systems/tl/base/ones.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface Ones {
(x1: number): string
(x1: Digit): string
}

/**


+ 4
- 3
src/systems/tl/base/tenPlus.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenPlus {
(ones: number): string
(ones: Digit): string
}

/**
@@ -9,6 +10,6 @@ interface TenPlus {
* @param {number} x1 - The number in the ones place.
* @returns {string} The name of the number plus ten.
*/
const tenPlus: TenPlus = (x1) => (x1 === 0 ? NAMES.tenTimes[1] : NAMES.tenPlus[x1])
const tenPlus: TenPlus = (x1) => (Number(x1) === 0 ? NAMES.tenTimes[1] : NAMES.tenPlus[x1])

export default tenPlus

+ 3
- 2
src/systems/tl/base/tenTimes.ts View File

@@ -1,7 +1,8 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'

interface TenTimes {
(x10: number): string
(x10: Digit): string
}

/**


+ 3
- 2
src/systems/tl/construct/tens.ts View File

@@ -1,10 +1,11 @@
import NAMES from '../names.json'
import { Digit } from '../../../common'
import NAMES from '../names'
import ones from '../base/ones'
import tenPlus from '../base/tenPlus'
import getBaseTenTimesName from '../base/tenTimes'

interface Tens {
(x10: number, x1: number): string
(x10: Digit, x1: Digit): string
}

const tens: Tens = (x10, x1) => {


+ 9
- 9
src/systems/tl/getKiloCount.test.ts View File

@@ -46,15 +46,15 @@ describe.each`
test.each`
ones | tenPlusName
${0} | ${' at sampu'}
${1} | ${' labing-isa'}
${2} | ${' labindalawa'}
${3} | ${' labintatlo'}
${4} | ${' labing-apat'}
${5} | ${' labinlima'}
${6} | ${' labing-anim'}
${7} | ${' labimpito'}
${8} | ${' labingwalo'}
${9} | ${' labinsiyam'}
${1} | ${' at labing-isa'}
${2} | ${' at labindalawa'}
${3} | ${' at labintatlo'}
${4} | ${' at labing-apat'}
${5} | ${' at labinlima'}
${6} | ${' at labing-anim'}
${7} | ${' at labimpito'}
${8} | ${' at labingwalo'}
${9} | ${' at labinsiyam'}
`(`should return "${hundredsName}$tenPlusName" for ${hundreds}1$ones`, ({ ones, tenPlusName }) => {
expect(getKiloCount(hundreds, 1, ones)).toBe([hundredsName, tenPlusName].join(''))
})


+ 3
- 3
src/systems/tl/getKiloCount.ts View File

@@ -1,5 +1,5 @@
import NAMES from './names.json'
import { GetKiloCount } from '../../NumberSystem'
import { GetKiloCount } from '../../common'
import NAMES from './names'
import constructTens from './construct/tens'
import hundredTimes from './base/hundredTimes'

@@ -14,7 +14,7 @@ const getKiloCount: GetKiloCount = (x100, x10, x1) => {
}
return [hundredTimes(x100), NAMES.and, constructTens(0, x1)].join(' ')
}
if (x1 === 0) {
if (x10 === 1 || x1 === 0) {
return [hundredTimes(x100), NAMES.and, constructTens(x10, x1)].join(' ')
}
return [hundredTimes(x100), constructTens(x10, x1)].join(' ')


+ 120
- 0
src/systems/tl/getShortKiloName.test.ts View File

@@ -0,0 +1,120 @@
import getShortKiloName from './getShortKiloName'

it('should exist', () => {
expect(getShortKiloName).toBeDefined()
})

it('should be a callable', () => {
expect(typeof getShortKiloName).toBe('function')
})

it('should accept 1 argument', () => {
expect(getShortKiloName).toHaveLength(1)
})

test.each`
thousandPower | name
${0n} | ${''}
${1n} | ${'libo'}
${2n} | ${'milyon'}
${3n} | ${'bilyon'}
${4n} | ${'trilyon'}
${5n} | ${'kuwadrilyon'}
${6n} | ${'kuwintilyon'}
${7n} | ${'sekstilyon'}
${8n} | ${'septilyon'}
${9n} | ${'oktilyon'}
${10n} | ${'nonilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${11n} | ${'desilyon'}
${21n} | ${'bihintilyon'}
${31n} | ${'trihintilyon'}
${41n} | ${'kuwadrahintilyon'}
${51n} | ${'kuwinkuwahintilyon'}
${61n} | ${'seksahintilyon'}
${71n} | ${'septuwahintilyon'}
${81n} | ${'oktohintilyon'}
${91n} | ${'nonahintilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${101n} | ${'sentilyon'}
${201n} | ${'duwosentilyon'}
${301n} | ${'tresentilyon'}
${401n} | ${'kuwadringhentilyon'}
${501n} | ${'kuwinghentilyon'}
${601n} | ${'sesentilyon'}
${701n} | ${'septinghentilyon'}
${801n} | ${'oktinghentilyon'}
${901n} | ${'nonghentilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${1001n} | ${'milyatilyon'}
${2001n} | ${'duwomilyatilyon'}
${3001n} | ${'tremilyatilyon'}
${4001n} | ${'kuwatuwormilyatilyon'}
${5001n} | ${'kuwinmilyatilyon'}
${6001n} | ${'seksmilyatilyon'}
${7001n} | ${'septenmilyatilyon'}
${8001n} | ${'oktomilyatilyon'}
${9001n} | ${'nobemmilyatilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${10001n} | ${'desmilyatilyon'}
${20001n} | ${'bihinmilyatilyon'}
${30001n} | ${'trihinmilyatilyon'}
${40001n} | ${'kuwadrahinmilyatilyon'}
${50001n} | ${'kuwinkuwahinmilyatilyon'}
${60001n} | ${'seksahinmilyatilyon'}
${70001n} | ${'septuwahinmilyatilyon'}
${80001n} | ${'oktohinmilyatilyon'}
${90001n} | ${'nonahinmilyatilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${100001n} | ${'senmilyatilyon'}
${200001n} | ${'duwosenmilyatilyon'}
${300001n} | ${'tresenmilyatilyon'}
${400001n} | ${'kuwadringhenmilyatilyon'}
${500001n} | ${'kuwinghenmilyatilyon'}
${600001n} | ${'sesenmilyatilyon'}
${700001n} | ${'septinghenmilyatilyon'}
${800001n} | ${'oktinghenmilyatilyon'}
${900001n} | ${'nonghenmilyatilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

test.each`
thousandPower | name
${1000001n} | ${'milyamilyatilyon'}
${2000001n} | ${'duwomilyamilyatilyon'}
${3000001n} | ${'tremilyamilyatilyon'}
${4000001n} | ${'kuwatuwormilyamilyatilyon'}
${5000001n} | ${'kuwinmilyamilyatilyon'}
${6000001n} | ${'seksmilyamilyatilyon'}
${7000001n} | ${'septenmilyamilyatilyon'}
${8000001n} | ${'oktomilyamilyatilyon'}
${9000001n} | ${'nobemmilyamilyatilyon'}
`('should return "$name" for 1000^$thousandPower', ({ name, thousandPower }) => {
expect(getShortKiloName(thousandPower)).toBe(name)
})

+ 20
- 0
src/systems/tl/getShortKiloName.ts View File

@@ -0,0 +1,20 @@
import { GetKiloName, Digit } from '../../common'
import NAMES from './names'
import getKiloCombiningPrefix from './base/kilo/combiningPrefix'

const getKiloName: GetKiloName = (thousandPower) => {
if (thousandPower === 0n) {
return ''
}
if (thousandPower === 1n) {
return NAMES.thousand
}
const kilo = thousandPower - 1n
const kiloHundreds = kilo / 100n
const kiloTens = (Number(kilo / 10n) % 10) as Digit
const kiloOnes = (Number(kilo) % 10) as Digit

return getKiloCombiningPrefix(kiloHundreds, kiloTens, kiloOnes) + NAMES.kiloEvenSuffix
}

export default getKiloName

+ 14
- 0
src/systems/tl/index.ts View File

@@ -0,0 +1,14 @@
import { NumberSystem } from '../../common'
import getKiloCount from './getKiloCount'
import getShortKiloName from './getShortKiloName'
import joinKilo from './joinKilo'

const numberSystem: NumberSystem = {
getKiloCount,
getKiloName: {
short: getShortKiloName,
},
joinKilo,
}

export default numberSystem

+ 18
- 0
src/systems/tl/joinKilo.ts View File

@@ -0,0 +1,18 @@
import { JoinKilo } from '../../common'

const joinKilo: JoinKilo = (kiloCount, kiloName) => {
const kiloCountLastLetter = kiloCount.slice(-1)
let kiloCountSuffix = ' na '

if (['a', 'o'].includes(kiloCountLastLetter)) {
kiloCountSuffix = 'ng '
}

if ('n' === kiloCountLastLetter) {
kiloCountSuffix = 'g '
}

return [kiloCount, kiloCountSuffix, kiloName].join('')
}

export default joinKilo

+ 0
- 92
src/systems/tl/names.json View File

@@ -1,92 +0,0 @@
{
"units": [
"sero",
"isa",
"dalawa",
"tatlo",
"apat",
"lima",
"anim",
"pito",
"walo",
"siyam"
],
"tenPlus": [
"sampu",
"labing-isa",
"labindalawa",
"labintatlo",
"labing-apat",
"labinlima",
"labing-anim",
"labimpito",
"labingwalo",
"labinsiyam"
],
"tenTimes": [
"sero",
"sampu",
"dalawampu",
"tatlumpu",
"apatnapu",
"limampu",
"animnapu",
"pitumpu",
"walumpu",
"siyamnapu"
],
"hundred": "daan",
"thousand": "libo",
"kiloSpecialUnits": [
"",
"m",
"b",
"tr",
"kuwadr",
"kuwin",
"seks",
"sept",
"okt",
"non"
],
"kiloUnits": [
"",
"un",
"duwo",
"tre",
"kuwatuwor",
"kuwin",
"seks",
"septen",
"okto",
"nobem"
],
"kiloTens": [
"",
"des",
"bihin",
"trihin",
"kuwadrahin",
"kuwinkuwahin",
"seksahin",
"septuwahin",
"oktohin",
"nonahin"
],
"kiloHundreds": [
"",
"sen",
"duwosen",
"tresen",
"kuwadringhen",
"kuwinghen",
"sesen",
"septinghen",
"oktinghen",
"nonghen"
],
"kiloThousand": "milya",
"kiloEvenSuffix": "lyon",
"kiloOddSuffix": "lyard",
"and": "at"
}

+ 63
- 0
src/systems/tl/names.ts View File

@@ -0,0 +1,63 @@
import { NumberSystemNameTable } from '../../common'

const names: NumberSystemNameTable = {
units: ['sero', 'isa', 'dalawa', 'tatlo', 'apat', 'lima', 'anim', 'pito', 'walo', 'siyam'],
tenPlus: [
'sampu',
'labing-isa',
'labindalawa',
'labintatlo',
'labing-apat',
'labinlima',
'labing-anim',
'labimpito',
'labingwalo',
'labinsiyam',
],
tenTimes: [
'sero',
'sampu',
'dalawampu',
'tatlumpu',
'apatnapu',
'limampu',
'animnapu',
'pitumpu',
'walumpu',
'siyamnapu',
],
hundred: 'daan',
thousand: 'libo',
kiloSpecialUnits: ['', 'm', 'b', 'tr', 'kuwadr', 'kuwin', 'seks', 'sept', 'okt', 'non'],
kiloUnits: ['', 'un', 'duwo', 'tre', 'kuwatuwor', 'kuwin', 'seks', 'septen', 'okto', 'nobem'],
kiloTens: [
'',
'des',
'bihin',
'trihin',
'kuwadrahin',
'kuwinkuwahin',
'seksahin',
'septuwahin',
'oktohin',
'nonahin',
],
kiloHundreds: [
'',
'sen',
'duwosen',
'tresen',
'kuwadringhen',
'kuwinghen',
'sesen',
'septinghen',
'oktinghen',
'nonghen',
],
kiloThousand: 'milya',
kiloEvenSuffix: 'lyon',
kiloOddSuffix: 'lyard',
and: 'at',
}

export default names

+ 1
- 0
tsconfig.json View File

@@ -2,6 +2,7 @@
"include": ["src", "types"],
"compilerOptions": {
"module": "esnext",
"target": "ES2020",
"lib": ["dom", "esnext"],
"importHelpers": true,
"declaration": true,