@obinexusmk2/hypernum 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +355 -256
- package/dist/index.cjs +4 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -7
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/types/{config → src/config}/config-loader.d.ts +0 -0
- package/dist/types/src/config/config-loader.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-parser.d.ts +0 -0
- package/dist/types/src/config/config-parser.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-resolver.d.ts +0 -0
- package/dist/types/src/config/config-resolver.d.ts.map +1 -0
- package/dist/types/{config → src/config}/config-source.d.ts +0 -0
- package/dist/types/src/config/config-source.d.ts.map +1 -0
- package/dist/types/{config → src/config}/index.d.ts +0 -0
- package/dist/types/src/config/index.d.ts.map +1 -0
- package/dist/types/{core → src/core}/common.d.ts +0 -0
- package/dist/types/src/core/common.d.ts.map +1 -0
- package/dist/types/{core → src/core}/config.d.ts +0 -0
- package/dist/types/src/core/config.d.ts.map +1 -0
- package/dist/types/{core → src/core}/constants.d.ts +0 -0
- package/dist/types/src/core/constants.d.ts.map +1 -0
- package/dist/types/{core → src/core}/errors.d.ts +0 -0
- package/dist/types/src/core/errors.d.ts.map +1 -0
- package/dist/types/{core → src/core}/hypernum.d.ts +0 -0
- package/dist/types/src/core/hypernum.d.ts.map +1 -0
- package/dist/types/{core → src/core}/index.d.ts +0 -0
- package/dist/types/src/core/index.d.ts.map +1 -0
- package/dist/types/{index.d.ts → src/index.d.ts} +1 -1
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/arithmetic.d.ts +0 -0
- package/dist/types/src/operations/arithmetic.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/bitwise.d.ts +0 -0
- package/dist/types/src/operations/bitwise.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/comparison.d.ts +0 -0
- package/dist/types/src/operations/comparison.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/conversion.d.ts +0 -0
- package/dist/types/src/operations/conversion.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/factorial.d.ts +0 -0
- package/dist/types/src/operations/factorial.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/index.d.ts +0 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/{operations → src/operations}/power.d.ts +0 -0
- package/dist/types/src/operations/power.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/Heap.d.ts +0 -0
- package/dist/types/src/storage/Heap.d.ts.map +1 -0
- package/dist/types/{storage → src/storage}/index.d.ts +0 -0
- package/dist/types/src/storage/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/ackermann.d.ts +0 -0
- package/dist/types/src/structures/ackermann.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/big-array.d.ts +0 -0
- package/dist/types/src/structures/big-array.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/index.d.ts +0 -0
- package/dist/types/src/structures/index.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/number-tree.d.ts +0 -0
- package/dist/types/src/structures/number-tree.d.ts.map +1 -0
- package/dist/types/{structures → src/structures}/power-tower.d.ts +0 -0
- package/dist/types/src/structures/power-tower.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/formatting.d.ts +0 -0
- package/dist/types/src/utils/formatting.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/index.d.ts +0 -0
- package/dist/types/src/utils/index.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/parser.d.ts +0 -0
- package/dist/types/src/utils/parser.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/precision.d.ts +0 -0
- package/dist/types/src/utils/precision.d.ts.map +1 -0
- package/dist/types/{utils → src/utils}/validation.d.ts +0 -0
- package/dist/types/src/utils/validation.d.ts.map +1 -0
- package/package.json +169 -164
- package/rollup.config.js +163 -161
- package/src/cli/hypernum.js +272 -0
- package/src/config/config-loader.ts +0 -0
- package/src/config/config-parser.ts +160 -160
- package/src/config/config-resolver.ts +0 -0
- package/src/config/config-source.ts +0 -0
- package/src/config/index.ts +0 -0
- package/src/core/common.ts +184 -184
- package/src/core/config.ts +392 -392
- package/src/core/constants.ts +101 -101
- package/src/core/errors.ts +202 -202
- package/src/core/hypernum.ts +240 -240
- package/src/core/index.ts +4 -4
- package/src/index.ts +179 -182
- package/src/operations/arithmetic.ts +332 -332
- package/src/operations/bitwise.ts +366 -366
- package/src/operations/comparison.ts +271 -271
- package/src/operations/conversion.ts +399 -399
- package/src/operations/factorial.ts +278 -278
- package/src/operations/index.ts +4 -4
- package/src/operations/power.ts +315 -315
- package/src/storage/Heap.ts +237 -237
- package/src/storage/index.ts +0 -0
- package/src/structures/ackermann.ts +232 -232
- package/src/structures/big-array.ts +305 -305
- package/src/structures/index.ts +3 -3
- package/src/structures/number-tree.ts +403 -403
- package/src/structures/power-tower.ts +277 -277
- package/src/types/common.d.ts +356 -356
- package/src/types/core.d.ts +160 -160
- package/src/types/index.d.ts +1 -1
- package/src/utils/formatting.ts +245 -245
- package/src/utils/index.ts +4 -4
- package/src/utils/parser.ts +244 -244
- package/src/utils/precision.ts +216 -216
- package/src/utils/validation.ts +182 -182
- package/tsconfig.json +83 -83
- package/dist/types/config/config-loader.d.ts.map +0 -1
- package/dist/types/config/config-parser.d.ts.map +0 -1
- package/dist/types/config/config-resolver.d.ts.map +0 -1
- package/dist/types/config/config-source.d.ts.map +0 -1
- package/dist/types/config/index.d.ts.map +0 -1
- package/dist/types/core/common.d.ts.map +0 -1
- package/dist/types/core/config.d.ts.map +0 -1
- package/dist/types/core/constants.d.ts.map +0 -1
- package/dist/types/core/errors.d.ts.map +0 -1
- package/dist/types/core/hypernum.d.ts.map +0 -1
- package/dist/types/core/index.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/operations/arithmetic.d.ts.map +0 -1
- package/dist/types/operations/bitwise.d.ts.map +0 -1
- package/dist/types/operations/comparison.d.ts.map +0 -1
- package/dist/types/operations/conversion.d.ts.map +0 -1
- package/dist/types/operations/factorial.d.ts.map +0 -1
- package/dist/types/operations/index.d.ts.map +0 -1
- package/dist/types/operations/power.d.ts.map +0 -1
- package/dist/types/storage/Heap.d.ts.map +0 -1
- package/dist/types/storage/index.d.ts.map +0 -1
- package/dist/types/structures/ackermann.d.ts.map +0 -1
- package/dist/types/structures/big-array.d.ts.map +0 -1
- package/dist/types/structures/index.d.ts.map +0 -1
- package/dist/types/structures/number-tree.d.ts.map +0 -1
- package/dist/types/structures/power-tower.d.ts.map +0 -1
- package/dist/types/utils/formatting.d.ts.map +0 -1
- package/dist/types/utils/index.d.ts.map +0 -1
- package/dist/types/utils/parser.d.ts.map +0 -1
- package/dist/types/utils/precision.d.ts.map +0 -1
- package/dist/types/utils/validation.d.ts.map +0 -1
package/src/utils/formatting.ts
CHANGED
|
@@ -1,246 +1,246 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Formatting utilities for Hypernum library
|
|
3
|
-
* Provides functions for formatting large numbers and converting between different representations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ValidationError } from './validation';
|
|
7
|
-
|
|
8
|
-
// Types for formatting options
|
|
9
|
-
export interface FormatOptions {
|
|
10
|
-
notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
|
|
11
|
-
precision?: number;
|
|
12
|
-
grouping?: boolean;
|
|
13
|
-
groupSize?: number;
|
|
14
|
-
decimalSeparator?: string;
|
|
15
|
-
groupSeparator?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ScientificNotation {
|
|
19
|
-
coefficient: string;
|
|
20
|
-
exponent: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface ScientificNotation {
|
|
24
|
-
coefficient: string;
|
|
25
|
-
exponent: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Default formatting options
|
|
29
|
-
const DEFAULT_OPTIONS: Required<FormatOptions> = {
|
|
30
|
-
notation: 'standard',
|
|
31
|
-
precision: 0,
|
|
32
|
-
grouping: true,
|
|
33
|
-
groupSize: 3,
|
|
34
|
-
decimalSeparator: '.',
|
|
35
|
-
groupSeparator: ',',
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Formats a BigInt value according to specified options
|
|
40
|
-
*/
|
|
41
|
-
export const formatBigInt = (value: bigint, options: FormatOptions = {}): string => {
|
|
42
|
-
const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };
|
|
43
|
-
|
|
44
|
-
// Handle negative numbers
|
|
45
|
-
const isNegative = value < BigInt(0);
|
|
46
|
-
const absValue = isNegative ? -value : value;
|
|
47
|
-
|
|
48
|
-
let result: string;
|
|
49
|
-
switch (opts.notation) {
|
|
50
|
-
case 'scientific':
|
|
51
|
-
result = formatScientific(absValue, opts).coefficient + 'e' +
|
|
52
|
-
formatScientific(absValue, opts).exponent;
|
|
53
|
-
break;
|
|
54
|
-
case 'engineering':
|
|
55
|
-
result = formatEngineering(absValue, opts);
|
|
56
|
-
break;
|
|
57
|
-
case 'compact':
|
|
58
|
-
result = formatCompact(absValue, opts);
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
result = formatStandard(absValue, opts);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return isNegative ? '-' + result : result;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Formats a number in standard notation with grouping
|
|
69
|
-
*/
|
|
70
|
-
const formatStandard = (value: bigint, options: Required<FormatOptions>): string => {
|
|
71
|
-
let str = value.toString();
|
|
72
|
-
|
|
73
|
-
if (!options.grouping) {
|
|
74
|
-
return str;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Apply grouping from the right
|
|
78
|
-
const result: string[] = [];
|
|
79
|
-
let position = str.length;
|
|
80
|
-
|
|
81
|
-
while (position > 0) {
|
|
82
|
-
const start = Math.max(0, position - options.groupSize);
|
|
83
|
-
result.unshift(str.slice(start, position));
|
|
84
|
-
position = start;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return result.join(options.groupSeparator);
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Converts a number to scientific notation
|
|
92
|
-
*/
|
|
93
|
-
const formatScientific = (value: bigint, options: Required<FormatOptions>): ScientificNotation => {
|
|
94
|
-
if (value === BigInt(0)) {
|
|
95
|
-
return { coefficient: '0', exponent: 0 };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const str = value.toString();
|
|
99
|
-
const exponent = str.length - 1;
|
|
100
|
-
|
|
101
|
-
let coefficient = str[0] || '';
|
|
102
|
-
coefficient += options.decimalSeparator + str.slice(1, options.precision + 1);
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
coefficient: coefficient,
|
|
106
|
-
exponent: exponent,
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Formats a number in engineering notation (exponents divisible by 3)
|
|
112
|
-
*/
|
|
113
|
-
const formatEngineering = (value: bigint, options: Required<FormatOptions>): string => {
|
|
114
|
-
if (value === BigInt(0)) {
|
|
115
|
-
return '0';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const str = value.toString();
|
|
119
|
-
const len = str.length;
|
|
120
|
-
const exponent = Math.floor((len - 1) / 3) * 3;
|
|
121
|
-
|
|
122
|
-
let coefficient = '';
|
|
123
|
-
const digitsBeforePoint = len - exponent;
|
|
124
|
-
|
|
125
|
-
for (let i = 0; i < Math.min(len, digitsBeforePoint + options.precision); i++) {
|
|
126
|
-
if (i === digitsBeforePoint && i < len) {
|
|
127
|
-
coefficient += options.decimalSeparator;
|
|
128
|
-
}
|
|
129
|
-
coefficient += str[i];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return `${coefficient}e${exponent}`;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Formats a number in compact notation (K, M, B, T)
|
|
137
|
-
*/
|
|
138
|
-
const formatCompact = (value: bigint, options: Required<FormatOptions>): string => {
|
|
139
|
-
const suffixes = ['', 'K', 'M', 'B', 'T', 'Q'];
|
|
140
|
-
const str = value.toString();
|
|
141
|
-
const len = str.length;
|
|
142
|
-
|
|
143
|
-
if (len <= 3) {
|
|
144
|
-
return formatStandard(value, options);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const suffixIndex = Math.min(Math.floor((len - 1) / 3), suffixes.length - 1);
|
|
148
|
-
const suffix = suffixes[suffixIndex];
|
|
149
|
-
|
|
150
|
-
const scale = BigInt(10) ** BigInt(suffixIndex * 3);
|
|
151
|
-
const scaledValue = value / scale;
|
|
152
|
-
|
|
153
|
-
let result = scaledValue.toString();
|
|
154
|
-
if (options.precision > 0) {
|
|
155
|
-
const remainder = value % scale;
|
|
156
|
-
if (remainder > BigInt(0)) {
|
|
157
|
-
const decimalPart = remainder.toString().padStart(3, '0').slice(0, options.precision);
|
|
158
|
-
result += options.decimalSeparator + decimalPart;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return result + suffix;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Parses a formatted string back to BigInt
|
|
167
|
-
*/
|
|
168
|
-
export const parseBigIntString = (str: string, options: FormatOptions = {}): bigint => {
|
|
169
|
-
const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };
|
|
170
|
-
|
|
171
|
-
// Remove grouping separators
|
|
172
|
-
let cleanStr = str.replace(new RegExp(`\\${opts.groupSeparator}`, 'g'), '');
|
|
173
|
-
|
|
174
|
-
// Handle scientific notation
|
|
175
|
-
if (cleanStr.toLowerCase().includes('e')) {
|
|
176
|
-
const [coefficient, exponent] = cleanStr.toLowerCase().split('e');
|
|
177
|
-
const base = BigInt(10);
|
|
178
|
-
const exp = BigInt(exponent || '0');
|
|
179
|
-
return BigInt(Math.floor(Number(coefficient))) * (base ** exp);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Handle suffixes
|
|
183
|
-
const suffixMap = new Map([
|
|
184
|
-
['k', BigInt(1000)],
|
|
185
|
-
['m', BigInt(1000000)],
|
|
186
|
-
['b', BigInt(1000000000)],
|
|
187
|
-
['t', BigInt(1000000000000)],
|
|
188
|
-
['q', BigInt(1000000000000000)],
|
|
189
|
-
]);
|
|
190
|
-
|
|
191
|
-
const suffix = cleanStr.slice(-1).toLowerCase();
|
|
192
|
-
const multiplier = suffixMap.get(suffix);
|
|
193
|
-
if (multiplier) {
|
|
194
|
-
cleanStr = cleanStr.slice(0, -1);
|
|
195
|
-
const value = BigInt(Math.floor(Number(cleanStr)));
|
|
196
|
-
return value * multiplier;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Handle regular numbers
|
|
200
|
-
return BigInt(cleanStr);
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Normalizes a string representation for comparison
|
|
205
|
-
*/
|
|
206
|
-
export const normalizeNumberString = (str: string): string => {
|
|
207
|
-
// Remove all spaces and separators
|
|
208
|
-
str = str.replace(/[\s,]/g, '');
|
|
209
|
-
|
|
210
|
-
// Handle scientific notation
|
|
211
|
-
if (str.toLowerCase().includes('e')) {
|
|
212
|
-
const [coefficient, exponent] = str.toLowerCase().split('e');
|
|
213
|
-
const exp = parseInt(exponent || '0');
|
|
214
|
-
const coef = parseFloat(coefficient || '0');
|
|
215
|
-
return (coef * Math.pow(10, exp)).toString();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return str;
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Formats a number for display in a tree structure
|
|
223
|
-
*/
|
|
224
|
-
export const formatTreeValue = (value: bigint, depth: number = 0): string => {
|
|
225
|
-
const indent = ' '.repeat(depth);
|
|
226
|
-
return `${indent}${formatBigInt(value, { notation: 'compact' })}`;
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Formats a range of numbers for display
|
|
231
|
-
*/
|
|
232
|
-
export const formatRange = (start: bigint, end: bigint, options: FormatOptions = {}): string => {
|
|
233
|
-
return `[${formatBigInt(start, options)} ... ${formatBigInt(end, options)}]`;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Formats a percentage
|
|
238
|
-
*/
|
|
239
|
-
export const formatPercentage = (value: bigint, total: bigint, precision: number = 2): string => {
|
|
240
|
-
if (total === BigInt(0)) {
|
|
241
|
-
throw new ValidationError('Cannot calculate percentage with zero total');
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const percentage = (Number(value) * 100) / Number(total);
|
|
245
|
-
return `${percentage.toFixed(precision)}%`;
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for Hypernum library
|
|
3
|
+
* Provides functions for formatting large numbers and converting between different representations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ValidationError } from './validation';
|
|
7
|
+
|
|
8
|
+
// Types for formatting options
|
|
9
|
+
export interface FormatOptions {
|
|
10
|
+
notation?: 'standard' | 'scientific' | 'engineering' | 'compact';
|
|
11
|
+
precision?: number;
|
|
12
|
+
grouping?: boolean;
|
|
13
|
+
groupSize?: number;
|
|
14
|
+
decimalSeparator?: string;
|
|
15
|
+
groupSeparator?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ScientificNotation {
|
|
19
|
+
coefficient: string;
|
|
20
|
+
exponent: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ScientificNotation {
|
|
24
|
+
coefficient: string;
|
|
25
|
+
exponent: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Default formatting options
|
|
29
|
+
const DEFAULT_OPTIONS: Required<FormatOptions> = {
|
|
30
|
+
notation: 'standard',
|
|
31
|
+
precision: 0,
|
|
32
|
+
grouping: true,
|
|
33
|
+
groupSize: 3,
|
|
34
|
+
decimalSeparator: '.',
|
|
35
|
+
groupSeparator: ',',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Formats a BigInt value according to specified options
|
|
40
|
+
*/
|
|
41
|
+
export const formatBigInt = (value: bigint, options: FormatOptions = {}): string => {
|
|
42
|
+
const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };
|
|
43
|
+
|
|
44
|
+
// Handle negative numbers
|
|
45
|
+
const isNegative = value < BigInt(0);
|
|
46
|
+
const absValue = isNegative ? -value : value;
|
|
47
|
+
|
|
48
|
+
let result: string;
|
|
49
|
+
switch (opts.notation) {
|
|
50
|
+
case 'scientific':
|
|
51
|
+
result = formatScientific(absValue, opts).coefficient + 'e' +
|
|
52
|
+
formatScientific(absValue, opts).exponent;
|
|
53
|
+
break;
|
|
54
|
+
case 'engineering':
|
|
55
|
+
result = formatEngineering(absValue, opts);
|
|
56
|
+
break;
|
|
57
|
+
case 'compact':
|
|
58
|
+
result = formatCompact(absValue, opts);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
result = formatStandard(absValue, opts);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return isNegative ? '-' + result : result;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Formats a number in standard notation with grouping
|
|
69
|
+
*/
|
|
70
|
+
const formatStandard = (value: bigint, options: Required<FormatOptions>): string => {
|
|
71
|
+
let str = value.toString();
|
|
72
|
+
|
|
73
|
+
if (!options.grouping) {
|
|
74
|
+
return str;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Apply grouping from the right
|
|
78
|
+
const result: string[] = [];
|
|
79
|
+
let position = str.length;
|
|
80
|
+
|
|
81
|
+
while (position > 0) {
|
|
82
|
+
const start = Math.max(0, position - options.groupSize);
|
|
83
|
+
result.unshift(str.slice(start, position));
|
|
84
|
+
position = start;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return result.join(options.groupSeparator);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Converts a number to scientific notation
|
|
92
|
+
*/
|
|
93
|
+
const formatScientific = (value: bigint, options: Required<FormatOptions>): ScientificNotation => {
|
|
94
|
+
if (value === BigInt(0)) {
|
|
95
|
+
return { coefficient: '0', exponent: 0 };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const str = value.toString();
|
|
99
|
+
const exponent = str.length - 1;
|
|
100
|
+
|
|
101
|
+
let coefficient = str[0] || '';
|
|
102
|
+
coefficient += options.decimalSeparator + str.slice(1, options.precision + 1);
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
coefficient: coefficient,
|
|
106
|
+
exponent: exponent,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Formats a number in engineering notation (exponents divisible by 3)
|
|
112
|
+
*/
|
|
113
|
+
const formatEngineering = (value: bigint, options: Required<FormatOptions>): string => {
|
|
114
|
+
if (value === BigInt(0)) {
|
|
115
|
+
return '0';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const str = value.toString();
|
|
119
|
+
const len = str.length;
|
|
120
|
+
const exponent = Math.floor((len - 1) / 3) * 3;
|
|
121
|
+
|
|
122
|
+
let coefficient = '';
|
|
123
|
+
const digitsBeforePoint = len - exponent;
|
|
124
|
+
|
|
125
|
+
for (let i = 0; i < Math.min(len, digitsBeforePoint + options.precision); i++) {
|
|
126
|
+
if (i === digitsBeforePoint && i < len) {
|
|
127
|
+
coefficient += options.decimalSeparator;
|
|
128
|
+
}
|
|
129
|
+
coefficient += str[i];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return `${coefficient}e${exponent}`;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Formats a number in compact notation (K, M, B, T)
|
|
137
|
+
*/
|
|
138
|
+
const formatCompact = (value: bigint, options: Required<FormatOptions>): string => {
|
|
139
|
+
const suffixes = ['', 'K', 'M', 'B', 'T', 'Q'];
|
|
140
|
+
const str = value.toString();
|
|
141
|
+
const len = str.length;
|
|
142
|
+
|
|
143
|
+
if (len <= 3) {
|
|
144
|
+
return formatStandard(value, options);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const suffixIndex = Math.min(Math.floor((len - 1) / 3), suffixes.length - 1);
|
|
148
|
+
const suffix = suffixes[suffixIndex];
|
|
149
|
+
|
|
150
|
+
const scale = BigInt(10) ** BigInt(suffixIndex * 3);
|
|
151
|
+
const scaledValue = value / scale;
|
|
152
|
+
|
|
153
|
+
let result = scaledValue.toString();
|
|
154
|
+
if (options.precision > 0) {
|
|
155
|
+
const remainder = value % scale;
|
|
156
|
+
if (remainder > BigInt(0)) {
|
|
157
|
+
const decimalPart = remainder.toString().padStart(3, '0').slice(0, options.precision);
|
|
158
|
+
result += options.decimalSeparator + decimalPart;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return result + suffix;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Parses a formatted string back to BigInt
|
|
167
|
+
*/
|
|
168
|
+
export const parseBigIntString = (str: string, options: FormatOptions = {}): bigint => {
|
|
169
|
+
const opts: Required<FormatOptions> = { ...DEFAULT_OPTIONS, ...options };
|
|
170
|
+
|
|
171
|
+
// Remove grouping separators
|
|
172
|
+
let cleanStr = str.replace(new RegExp(`\\${opts.groupSeparator}`, 'g'), '');
|
|
173
|
+
|
|
174
|
+
// Handle scientific notation
|
|
175
|
+
if (cleanStr.toLowerCase().includes('e')) {
|
|
176
|
+
const [coefficient, exponent] = cleanStr.toLowerCase().split('e');
|
|
177
|
+
const base = BigInt(10);
|
|
178
|
+
const exp = BigInt(exponent || '0');
|
|
179
|
+
return BigInt(Math.floor(Number(coefficient))) * (base ** exp);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Handle suffixes
|
|
183
|
+
const suffixMap = new Map([
|
|
184
|
+
['k', BigInt(1000)],
|
|
185
|
+
['m', BigInt(1000000)],
|
|
186
|
+
['b', BigInt(1000000000)],
|
|
187
|
+
['t', BigInt(1000000000000)],
|
|
188
|
+
['q', BigInt(1000000000000000)],
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
const suffix = cleanStr.slice(-1).toLowerCase();
|
|
192
|
+
const multiplier = suffixMap.get(suffix);
|
|
193
|
+
if (multiplier) {
|
|
194
|
+
cleanStr = cleanStr.slice(0, -1);
|
|
195
|
+
const value = BigInt(Math.floor(Number(cleanStr)));
|
|
196
|
+
return value * multiplier;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Handle regular numbers
|
|
200
|
+
return BigInt(cleanStr);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Normalizes a string representation for comparison
|
|
205
|
+
*/
|
|
206
|
+
export const normalizeNumberString = (str: string): string => {
|
|
207
|
+
// Remove all spaces and separators
|
|
208
|
+
str = str.replace(/[\s,]/g, '');
|
|
209
|
+
|
|
210
|
+
// Handle scientific notation
|
|
211
|
+
if (str.toLowerCase().includes('e')) {
|
|
212
|
+
const [coefficient, exponent] = str.toLowerCase().split('e');
|
|
213
|
+
const exp = parseInt(exponent || '0');
|
|
214
|
+
const coef = parseFloat(coefficient || '0');
|
|
215
|
+
return (coef * Math.pow(10, exp)).toString();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return str;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Formats a number for display in a tree structure
|
|
223
|
+
*/
|
|
224
|
+
export const formatTreeValue = (value: bigint, depth: number = 0): string => {
|
|
225
|
+
const indent = ' '.repeat(depth);
|
|
226
|
+
return `${indent}${formatBigInt(value, { notation: 'compact' })}`;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Formats a range of numbers for display
|
|
231
|
+
*/
|
|
232
|
+
export const formatRange = (start: bigint, end: bigint, options: FormatOptions = {}): string => {
|
|
233
|
+
return `[${formatBigInt(start, options)} ... ${formatBigInt(end, options)}]`;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Formats a percentage
|
|
238
|
+
*/
|
|
239
|
+
export const formatPercentage = (value: bigint, total: bigint, precision: number = 2): string => {
|
|
240
|
+
if (total === BigInt(0)) {
|
|
241
|
+
throw new ValidationError('Cannot calculate percentage with zero total');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const percentage = (Number(value) * 100) / Number(total);
|
|
245
|
+
return `${percentage.toFixed(precision)}%`;
|
|
246
246
|
};
|
package/src/utils/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './validation'
|
|
2
|
-
export * from './precision'
|
|
3
|
-
export * from './formatting'
|
|
4
|
-
export * from './parser'
|
|
1
|
+
export * from './validation'
|
|
2
|
+
export * from './precision'
|
|
3
|
+
export * from './formatting'
|
|
4
|
+
export * from './parser'
|