|
- import BigNumber from 'bignumber.js';
-
- const EXPONENT_SEPARATOR = 'e'
- const SIGNIFICAND_DECIMAL_POINT = '.'
-
- export const NEGATIVE_SIGN = '-'
-
- export const BLANK_DIGIT = '0' // must be a value where Number(BLANK_DIGIT) === 0
-
- export type Numeric = number | bigint | string | BigNumber
-
- export type Group = [string, BigNumber]
-
- export const normalizeNumeric = (x: Numeric): string => {
- try {
- switch (typeof x) {
- case 'number':
- return new BigNumber(x).toString(10)
- case 'bigint':
- return x.toString(10)
- case 'string':
- // TODO assume not all strings follow a correct format
- return x
- // return new BigNumber(x).toString(10)
- case 'object':
- return x.toString(10)
- default:
- break
- }
- } catch {
- throw new RangeError('Not a valid numeric value in the current locale.')
- }
- throw new TypeError('Not a valid numeric value in any locale.')
- }
-
- export const deconstructNumeric = (x: string) => {
- const absolute = x.replaceAll(NEGATIVE_SIGN, '')
- if (!absolute.includes(EXPONENT_SEPARATOR)) {
- return {
- exponent: new BigNumber(absolute.length - 1),
- significandDigits: absolute,
- }
- }
- const [significandStrExp, exponentStr] = absolute.split(EXPONENT_SEPARATOR)
- const [integral] = significandStrExp.split(SIGNIFICAND_DECIMAL_POINT)
- return {
- exponent: new BigNumber(exponentStr).plus(integral.length - 1),
- significandDigits: significandStrExp.replaceAll(SIGNIFICAND_DECIMAL_POINT, '')
- }
- }
-
- export const createBlankDigits = (grouping: number) => new Array<string>(grouping).fill(BLANK_DIGIT).join('')
-
- export const groupDigits = (significandStr: string, exponent: BigNumber, grouping: number) => {
- const blankDigits = createBlankDigits(grouping)
- return significandStr
- .split('')
- .reduceRight(
- (theGroups, c, i): any => {
- const currentGroupIndex = exponent.minus(i).dividedToIntegerBy(grouping).minus(1)
- const [lastGroup = [blankDigits, currentGroupIndex.plus(1)] as Group] = theGroups
- const [digits, groupIndex] = lastGroup
- const currentPlaceValue = exponent.minus(i).mod(grouping)
- if (currentPlaceValue.eq(0)) {
- return [[`${blankDigits.slice(0, -c.length)}${c}`, currentGroupIndex.plus(1)], ...theGroups]
- }
- const currentDigitStringIndex = new BigNumber(grouping).minus(1).minus(currentPlaceValue).toNumber()
- const newDigits = digits.slice(0, currentDigitStringIndex) + c + digits.slice(currentDigitStringIndex + c.length)
- return [[newDigits, groupIndex] as Group, ...theGroups.slice(1)]
- },
- [] as Group[],
- )
- }
|